Amazon Sponsored Ad Placement Scraper가 96% 성공률을 달성하는 방법
Source: Dev.to
(번역할 텍스트를 제공해 주시면 한국어로 번역해 드리겠습니다.)
🚨 문제: 불완전한 데이터가 잘못된 의사결정을 초래한다
작년, 경쟁사의 광고 전략을 분석하던 중 우리 팀은 흥미로운 현상을 발견했습니다. 동일한 키워드 “wireless earbuds” 를 서로 다른 도구로 스크래핑했을 때, 스폰서드 프로덕트 광고 수가 크게 달라졌으며—때로는 두 배 차이가 났습니다.
처음엔 타이밍 문제라고 생각했습니다. 하지만 실제 상황은 더 우려스러웠습니다: 우리는 Amazon이 “의심스러운 방문자”에게 보여주도록 선택한 단순화된 버전만을 보고 있었던 것입니다.
이 사실을 알게 되면서 Amazon의 안티‑스크래핑 메커니즘을 파헤치는 긴 여정에 들어섰고, 10여 개가 넘는 솔루션을 테스트하며 상당한 프록시‑IP 예산을 소모했습니다. 오늘은 이러한 고생 끝에 얻은 인사이트를 공유하여 여러분이 같은 함정에 빠지지 않도록 돕고자 합니다.
Source: …
💰 왜 Amazon은 SP 광고 데이터를 이렇게 철저히 보호할까
솔직히 말하자면: Sponsored Products 광고는 Amazon의 돈 프린터다. 광고 클릭 하나하나가 실제 매출로 이어지기 때문에, Amazon은 이 데이터를 다섯 가지 정교한 장벽을 통해 거의 집착하듯 보호한다.
🔒 장벽 #1 – IP 평판 점수 시스템
- Amazon은 방대한 IP 평판 데이터베이스를 운영한다.
- 데이터센터 IP, 알려진 프록시 서버, 그리고 자주 회전하는 동적 IP는 고위험으로 표시된다.
- 일반 사용자 행동과 일치하지 않는 요청 패턴(예: 초당 여러 카테고리 검색 페이지에 접근)으로 나타나는 경우, 주거용 프록시 IP도 다운그레이드 처리를 유발할 수 있다.
시스템이 완전히 차단하는 것이 아니라, 광고 노출을 선택적으로 감소시키거나 낮은 입찰가의 광고만 표시한다.
🎭 장벽 #2 – JavaScript 동적 렌더링 함정
- SP 광고는 클라이언트‑사이드 JavaScript를 통해 삽입되므로, 단순 HTTP 요청만으로는 전체 내용을 캡처할 수 없다.
- Amazon 프런트엔드 코드에는 다양한 탐지 메커니즘이 포함되어 있다:
| 검사 항목 | 감지 내용 |
|---|---|
| ✅ Window 객체 완전성 | 누락되거나 변조된 속성 |
| ✅ WebGL 지문 검증 | 가짜 또는 누락된 GPU 정보 |
✅ navigator.webdriver 탐지 | 자동화 플래그 |
| ✅ Canvas 지문 | 헤드리스 브라우저 서명 |
이상 징후가 감지되면 광고 노출 렌더링 로직이 조용히 건너뛰어진다. 스크랩한 페이지는 정상처럼 보이지만 가장 핵심적인 데이터가 누락된다.
🌍 장벽 #3 – 지리적 위치 및 ZIP‑코드 매칭
- 동일 키워드라도 ZIP 코드에 따라 완전히 다른 광고가 표시될 수 있다(판매자가 특정 지역을 타깃팅하기 때문).
- 요청 IP의 지리적 위치가 선언된 ZIP‑코드 파라미터와 일치하지 않거나 명백한 국경 간 프록시를 사용할 경우, Amazon은 해당 요청을 의심스러워 하며 광고 내용을 제한한다.
🕵️ 장벽 #4 – 요청 빈도 및 세션 연속성
- 실제 사용자는 검색 결과 페이지에 머무르고, 스크롤하고, 클릭한다; 스크래퍼는 기계적인 규칙성을 보이는 경우가 많다.
- Amazon의 행동 분석 엔진은 각 세션의 경로를 추적해 비정상적인 패턴이 발견되면 광고 노출 전략을 강화한다.
누적 효과: 동일 IP 또는 디바이스 지문에서 여러 의심 행동이 겹치면 평판 점수가 지속적으로 하락하고, 결국 블랙리스트에 올려진다.
🎲 장벽 #5 – 광고 배치 블랙‑박스 알고리즘
첫 네 장벽을 모두 우회하더라도, SP 광고 자체는 실시간 입찰 블랙‑박스 시스템이다. 광고 수량, 위치, 구체적인 제품은 복잡하고 독점적인 알고리즘에 의해 동적으로 결정된다.
🛠️ Solution Matrix – From Small to Large Scale
| 규모 | 일일 요청 수 | 기술 | 성공률 | 월 비용 | 핵심 포인트 |
|---|---|---|---|---|---|
| 소규모 | 10,000 | 전문 API 서비스 | 90‑96 %+ | $3,500+ | • 안티 스크래핑 메커니즘을 우회하기 위해 대규모 자원을 투입 • 플랫폼 알고리즘 변경을 지속적으로 추적 • 구조화된 데이터 출력 • 성공적인 요청을 기준으로 청구. |
📊 실제 테스트 데이터 비교
100개의 키워드와 5개의 ZIP 코드를 대상으로 14 일간 테스트
| 솔루션 | 평균 성공률 | 고경쟁 성공률 | 비용 / 1K |
|---|---|---|---|
| 자체 구축 Selenium | 68 % | 52 % | $45 |
| ScraperAPI | 43 % | 38 % | $60+ |
| Bright Data | 79 % | 74 % | $120 |
| Pangolin Scrape API | 96.3 % | 92 % | $35 |
🏆 왜 Pangolin이 최고의 성능을 발휘할까요?
- Optimized IP network – specifically for Amazon; each IP undergoes long‑term “account nurturing.”
- Dynamic fingerprint generation – unique but reasonable browser fingerprints for every request.
- Intelligent request scheduling – algorithms adjust strategies based on real‑time feedback.
💻 코드 예제 – 빠른 시작
옵션 1: 기본 Puppeteer (소규모 테스트)
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
async function scrapeSponsoredAds(keyword, zipCode) {
const browser = await puppeteer.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-blink-features=AutomationControlled'
]
});
const page = await browser.newPage();
// Set realistic viewport & user‑agent
await page.setViewport({ width: 1280, height: 800 });
await page.setUserAgent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) ' +
'Chrome/124.0.0.0 Safari/537.36'
);
// Optional: add extra headers to mimic a real browser
await page.setExtraHTTPHeaders({
'Accept-Language': 'en-US,en;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
});
// Build Amazon search URL with ZIP code parameter
const url = `https://www.amazon.com/s?k=${encodeURIComponent(keyword)}&ref=nb_sb_noss_2&zipCode=${zipCode}`;
await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });
// Wait for SP ad container to load (adjust selector if needed)
await page.waitForSelector('[data-component-type="sponsored-product"]', { timeout: 15000 });
// Extract ad data
const ads = await page.evaluate(() => {
const nodes = document.querySelectorAll('[data-component-type="sponsored-product"]');
return Array.from(nodes).map(node => ({
title: node.querySelector('h2')?.innerText.trim(),
asin: node.getAttribute('data-asin'),
price: node.querySelector('.a-price-whole')?.innerText.trim(),
rating: node.querySelector('.a-icon-alt')?.innerText.trim(),
url: node.querySelector('a')?.href
}));
});
await browser.close();
return ads;
}
// Example usage
scrapeSponsoredAds('wireless earbuds', '10001')
.then(ads => console.log(JSON.stringify(ads, null, 2)))
.catch(err => console.error('Scrape error:', err));
옵션 2: Pangolin Scrape API 사용 (모든 규모)
# Bash – simple curl request
curl -X POST https://api.pangolin-scrape.com/v1/amazon/sp \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"keyword": "wireless earbuds",
"zip_code": "10001",
"locale": "en_US"
}'
# Python – wrapper library example
import requests
API_KEY = "YOUR_API_KEY"
endpoint = "https://api.pangolin-scrape.com/v1/amazon/sp"
payload = {
"keyword": "wireless earbuds",
"zip_code": "10001",
"locale": "en_US"
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
response = requests.post(endpoint, json=payload, headers=headers)
if response.ok:
ads = response.json()
print(ads)
else:
print("Error:", response.status_code, response.text)
📌 Takeaways
- 스크래퍼를 제한하고 있는 장벽을 식별하세요 – 먼저 IP 평판을 확인하고, 그 다음 JS 렌더링, 지리 매칭, 요청 빈도, 마지막으로 입찰 알고리즘 순으로 진행합니다.
- 규모에 맞는 솔루션을 선택하세요 – 소규모 프로젝트는 잘 튜닝된 Selenium 설정만으로도 충분하고, 중규모는 헤드리스 브라우저 팜이 필요하며, 대규모는 Amazon의 변동에 지속적으로 대응하는 전용 API가 최적입니다.
- 동적 지문 생성 및 현실적인 세션 행동에 투자하세요 – 정적 지문은 한계가 있으며, 트래픽이 실제 쇼핑객을 얼마나 잘 흉내 내느냐에 따라 성공률이 높아집니다.
스크래핑을 즐기세요 (책임감 있게)!
Amazon Sponsored Ad Placement Scraper
아래는 Amazon에서 Sponsored Product (SP) 광고 배치 데이터를 수집할 때 사용할 수 있는 두 가지 접근 방식입니다.
Option 1 – Headless Browser (Puppeteer)
const puppeteer = require('puppeteer');
async function getSponsoredAds(keyword, zipCode = '10001') {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
// Set a realistic user‑agent and location cookie
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36');
await page.setCookie({
name: 'zip',
value: zipCode,
domain: '.amazon.com'
});
// Build the search URL and navigate to it
const searchUrl = `https://www.amazon.com/s?k=${encodeURIComponent(keyword)}`;
await page.goto(searchUrl, { waitUntil: 'networkidle2' });
// Simulate human behavior
await page.evaluate(() => {
window.scrollBy(0, Math.random() * 500 + 300);
});
await new Promise(r => setTimeout(r, 2000 + Math.random() * 3000));
// Extract sponsored ads from the results page
const sponsoredAds = await page.evaluate(() => {
const ads = [];
document
.querySelectorAll('[data-component-type="s-search-result"]')
.forEach((el, i) => {
const badge = el.querySelector('.s-label-popover-default');
if (badge?.textContent.includes('Sponsored')) {
ads.push({
position: i + 1,
asin: el.getAttribute('data-asin'),
title: el.querySelector('h2')?.textContent.trim()
});
}
});
return ads;
});
await browser.close();
return sponsoredAds;
}
// Example usage
// (async () => {
// const ads = await getSponsoredAds('bluetooth speaker', '90001');
// console.log(ads);
// })();
Option 2 – Pangolin API (Production‑Ready)
const axios = require('axios');
class PangolinSPAdScraper {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.pangolinfo.com/scrape';
}
async getSponsoredAds(keyword, options = {}) {
const response = await axios.post(this.baseUrl, {
api_key: this.apiKey,
type: 'search',
amazon_domain: 'amazon.com',
keyword: keyword,
zip_code: options.zipCode || '10001',
output_format: 'json'
});
return response.data.search_results
.filter(item => item.is_sponsored)
.map(item => ({
position: item.position,
asin: item.asin,
title: item.title,
price: item.price,
adType: item.sponsored_type
}));
}
}
// Usage
const scraper = new PangolinSPAdScraper('YOUR_API_KEY');
scraper.getSponsoredAds('bluetooth speaker', { zipCode: '90001' })
.then(ads => console.log(`Found ${ads.length} ad placements`))
.catch(err => console.error('Error:', err));
🎯 나의 권장 사항
| 규모 | 권장 접근법 |
|---|---|
| 소규모 | Selenium/Puppeteer를 사용해 데이터를 파악해 보세요. |
| 중규모 | 탄탄한 개발팀이 있다면 작은 클러스터를 구축하고, 그렇지 않다면 바로 API를 사용하세요. |
| 대규모 | 전문 API를 사용하세요—절감되는 시간이 비용보다 훨씬 큽니다. |
핵심 원칙: 항상 실제 데이터를 통해 스크래핑 효과를 검증하세요. “일부 데이터를 스크랩할 수 있다”에 만족하지 말고, “모든 관련 데이터를 다 캡처했는가?”를 물어보세요.
🏁 Bottom Line
아마존의 데이터 기반 마켓플레이스에서 SP‑ad 데이터의 정확성은 비즈니스 의사결정에 직접적인 영향을 미칩니다. 광고 배치를 50 %만 수집하는 스크래퍼는 키워드 경쟁이 낮다고 오해하게 만들어 입찰이나 재고 선택을 잘못하게 할 수 있습니다.
신뢰할 수 있는 Sponsored Ad Placement Scraper를 구축하는 기술 장벽이 높기 때문에, 대부분의 팀은 핵심 제품 로직에 자원을 할당하고 데이터 수집을 신뢰할 수 있는 서비스에 아웃소싱하는 것이 유리합니다.
🔗 리소스
- Pangolin 웹사이트:
- API 문서:
- 개발자 콘솔: