대규모 Shein 스크래핑 2026: 카탈로그·가격·재고 데이터 수집 실전 가이드

Shein의 API vs HTML 트레이드오프부터 Akamai Bot Manager 우회, curl_cffi + ProxyHat 게이트웨이 연동, 세션 스티키 및 페이지네이션 처리까지 — 패션 가격 인텔리전스 팀을 위한 실전 구현 가이드.

Scraping Shein at Scale in 2026: A Practical Proxy & Anti-Bot Guide
이 글의 목차

대규모 Shein 스크래핑 2026: API 엔드포인트 vs 렌더링 HTML

패션 가격 인텔리전스 분석가라면, 대규모 Shein 스크래핑 2026 환경에서 가장 먼저 결정해야 할 것은 데이터를 어디서 가져올지입니다. Shein은 제품 상세 페이지의 렌더링된 HTML을 제공하지만, 동시에 /api/productInfo 및 제품 목록 JSON 엔드포인트 같은 내부 API도 노출합니다. 두 접근 방식 모두 장단점이 뚜렷합니다.

HTML 파싱은 productIntroDatagbProductDetail JSON 블롭이 페이지 소스에 임베드되어 있어 진입 장벽이 낮지만, Shein이 자주 변경하는 DOM 구조에 의존하게 됩니다. 반면 /api/productInfo 엔드포인트는 goods_id 파라미터로 직접 호출 가능하며 구조화된 JSON을 반환하지만, Akamai Bot Manager의 _abck 쿠키 검증을 통과해야 합니다. 대부분의 프로덕션 스크래퍼는 API 우선 전략을 채택하고 HTML을 폴백으로 사용합니다.

이 가이드에서는 Shein 스크래핑을 위한 전체 파이프라인 — anti-bot 스택 이해, 데이터 위치 식별, ProxyHat 게이트웨이 연동, 세션 관리, 윤리적 고려사항 — 을 단계별로 다룹니다.

Shein의 안티봇 스택 이해하기

Akamai Bot Manager와 _abck 쿠키

Shein은 Akamai Bot Manager를 핵심 봇 방어 계층으로 사용합니다. Akamai는 방문 시 _abck 쿠키와 bm_sz 쿠키를 설정하고, 브라우저가 sensor_data 텔레메트리를 수집하여 정기적으로 제출하도록 요구합니다. 이 텔레메트리는 캔버스 핑거프린팅, WebGL 렌더러 정보, 타이밍 데이터, 이벤트 시퀀스 등 수십 개의 신호를 포함합니다.

순수 headless Chrome — 예를 들어 undetected-chromedriver 없는 기본 Selenium — 은 Akamai의 센서 데이터 검증을 통과하지 못합니다. Akamai는 Chrome의 자동화 플래그, 누락된 이벤트 시퀀스, 비정상적인 타이밍 패턴을 감지하면 _abck 쿠키를 "검증 실패" 상태로 표시하고, 이후 요청에 HTTP 412 또는 403을 반환합니다.

smdeviceid 디바이스 토큰

Shein은 추가로 smdeviceid라는 디바이스 식별 토큰을 사용합니다. 이 값은 클라이언트 측 JavaScript에서 생성되어 모든 API 요청 헤더에 포함됩니다. smdeviceid가 누락되거나 일관성이 없으면, 유효한 _abck 쿠키가 있어도 요청이 거부될 수 있습니다. 대규모 수집에서는 디바이스 토큰 풀을 관리하고 세션별로 일관된 토큰을 유지하는 것이 중요합니다.

핵심 인사이트: headless Chrome만으로 Shein을 스크래핑하면 안 됩니다. TLS 지문, 센서 데이터, 디바이스 토큰이 모두 일치해야 하며, 그 위에 IP 로테이션이 필요합니다.

데이터 위치: 어디서 가격·재고·SKU를 찾을까

상품 상세 페이지의 JSON 블롭

Shein 상품 페이지(https://www.shein.com/[product]-p-[goods_id].html)의 HTML 소스를 열면, 두 개의 핵심 JSON 블롭이 있습니다:

  • productIntroData — 제품 기본 정보, SKU 옵션, 이미지 URL, 색상/사이즈 매트릭스 포함
  • gbProductDetail — 가격 정보(retailPrice, salePrice), 재고 수량(stock), 프로모션 태그 포함

이 블롭들은 <script> 태그 내에 JSON으로 임베드되어 있으므로, 정규식이나 JSON 파서로 추출할 수 있습니다. 하지만 Shein이 DOM 구조를 변경해도 이 JSON 구조는 비교적 안정적입니다.

내부 API 엔드포인트

더 효율적인 경로는 Shein의 내부 API를 직접 호출하는 것입니다:

# 상품 상세 정보 (JSON)
https://www.shein.com/api/productInfo?goods_id=12345678&country=US

# 카테고리별 상품 목록
https://www.shein.com/api/category/product/list?cat_id=1&page=1&page_size=40&country=US

goods_id는 개별 상품 식별자이고, cat_id는 카테고리 식별자입니다. 카테고리 피드 엔드포인트는 페이지네이션을 지원하며, pagepage_size 파라미터로 제어합니다. page_size는 최대 120까지 설정 가능하지만, 40–60 사이가 안정적입니다.

샘플 응답 (truncated)

{
  "code": 0,
  "msg": "success",
  "data": {
    "goods_id": "12345678",
    "goods_name": "Solid Drop Shoulder Oversized Hoodie",
    "retailPrice": { "amount": "25.99", "amountWithSymbol": "$25.99" },
    "salePrice": { "amount": "12.99", "amountWithSymbol": "$12.99" },
    "stock": 3421,
    "sku_list": [
      { "sku_code": "SKU1", "color": "Black", "size": "M", "stock": 820 },
      { "sku_code": "SKU2", "color": "Black", "size": "L", "stock": 0 }
    ],
    "cat_id": "1730",
    "brand": "SHEIN"
  }
}

IP별 현실적 레이트 리밋과 프록시 로테이션

Shein은 IP당 요청 빈도를 제한합니다. 실측 기준, 단일 IP로 분당 약 30–50개 요청까지는 정상 응답을 받을 수 있지만, 이를 초과하면 412 Precondition Failed 또는 403 Forbidden이 반환됩니다. 더 중요한 것은 Shein이 지역별로 가격, 통화, 재고를 현지화한다는 점입니다. 미국 IP로 접속하면 USD 가격이, 독일 IP로 접속하면 EUR 가격이 표시됩니다. 동일 상품이라도 국가별 가격 차이가 10–30% 발생할 수 있습니다.

따라서 Shein 상품 스크래퍼를 구축할 때는 단순한 IP 로테이션이 아니라 지역 타겟팅이 가능한 주거용 프록시가 필수입니다. ProxyHat의 주거용 프록시는 -country-US, -country-DE 같은 플래그로 국가를 지정할 수 있어, 각 시장의 실제 가격을 정확히 수집할 수 있습니다.

또한, 세션 일관성도 중요합니다. 한 세션에서 통화가 USD로 설정된 후, 다른 요청에서 EUR로 바뀌면 데이터가 오염됩니다. ProxyHat의 -session- 플래그로 스티키 세션을 유지하면, 동일 IP에서 일관된 통화와 가격을 받을 수 있습니다.

프록시 유형 IP당 추천 요청 지역 타겟팅 세션 스티키 적합성
주거용 (Residential) 30–50/min 국가·도시 가능 최적 — Shein 1순위
모바일 (Mobile) 40–60/min 국가 가능 양호 — 4G/5G IP 신뢰도 높음
데이터센터 (Datacenter) 10–20/min 제한적 가능 부적합 — Akamai 차단 확률 높음

실전 구현: curl_cffi + ProxyHat으로 Shein 가격 데이터 수집

일반 requests 라이브러리는 TLS 지문이 Python의 기본 값으로 노출되어 Akamai에 쉽게 감지됩니다. curl_cffi는 Chrome의 TLS 지문을 모방하여 JA3 / JA4 검증을 우회할 수 있습니다. 아래는 curl_cffi와 ProxyHat 게이트웨이를 조합한 Shein 가격 데이터 수집 예제입니다.

from curl_cffi import requests as cffi_requests
import json
import time
import random

# ProxyHat 주거용 프록시 — 미국 지역, 스티키 세션
PROXY_URL = "http://user-country-US-session-shein01:pass@gate.proxyhat.com:8080"

HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
    "Accept": "application/json, text/plain, */*",
    "Accept-Language": "en-US,en;q=0.9",
    "Referer": "https://www.shein.com/",
}

def fetch_product(goods_id: str, max_retries: int = 3):
    url = f"https://www.shein.com/api/productInfo?goods_id={goods_id}&country=US"
    
    for attempt in range(max_retries):
        try:
            resp = cffi_requests.get(
                url,
                headers=HEADERS,
                proxies={"http": PROXY_URL, "https": PROXY_URL},
                impersonate="chrome131",
                timeout=15,
            )
            
            if resp.status_code == 412:
                # _abck 쿠키 갱신 필요 — 백오프 후 재시도
                wait = (2 ** attempt) + random.uniform(0.5, 1.5)
                print(f"412 received, backing off {wait:.1f}s")
                time.sleep(wait)
                continue
            
            if resp.status_code == 200:
                data = resp.json()
                if data.get("code") == 0:
                    product = data["data"]
                    return {
                        "goods_id": product["goods_id"],
                        "name": product["goods_name"],
                        "retail_price": product["retailPrice"]["amount"],
                        "sale_price": product["salePrice"]["amount"],
                        "stock": product["stock"],
                        "currency": "USD",
                    }
            
            print(f"Unexpected status: {resp.status_code}")
            time.sleep(1)
            
        except Exception as e:
            print(f"Error on attempt {attempt+1}: {e}")
            time.sleep(2 ** attempt)
    
    return None

# 사용 예시
result = fetch_product("12345678")
print(json.dumps(result, indent=2))

출력 예시:

{
  "goods_id": "12345678",
  "name": "Solid Drop Shoulder Oversized Hoodie",
  "retail_price": "25.99",
  "sale_price": "12.99",
  "stock": 3421,
  "currency": "USD"
}

Node.js 예제 (axios + ProxyHat)

const axios = require('axios');

const proxyConfig = {
  protocol: 'http',
  host: 'gate.proxyhat.com',
  port: 8080,
  auth: { username: 'user-country-DE-session-shein02', password: 'pass' }
};

async function fetchSheinProduct(goodsId) {
  const url = `https://www.shein.com/api/productInfo?goods_id=${goodsId}&country=DE`;
  const resp = await axios.get(url, {
    proxy: proxyConfig,
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
      'Accept-Language': 'de-DE,de;q=0.9',
      'Referer': 'https://www.shein.com/'
    },
    timeout: 15000
  });
  return resp.data;
}

curl 원라이너

curl -x http://user-country-US-session-shein01:pass@gate.proxyhat.com:8080 \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
  -H "Accept: application/json" \
  -H "Referer: https://www.shein.com/" \
  "https://www.shein.com/api/productInfo?goods_id=12345678&country=US"

페이지네이션, 스티키 세션, 백오프 전략

카테고리 피드 페이지네이션

카테고리 전체 상품을 수집하려면 page 파라미터를 증가시키며 반복 호출합니다. Shein 카테고리는 보통 2,000–10,000개 상품을 포함하므로, page_size=40 기준 50–250페이지까지 순회해야 합니다.

def scrape_category(cat_id: str, country: str = "US", max_pages: int = 100):
    all_products = []
    
    for page in range(1, max_pages + 1):
        # 페이지마다 새 세션 ID로 IP 로테이션
        session_id = f"shein-{country}-{page}"
        proxy = f"http://user-country-{country}-session-{session_id}:pass@gate.proxyhat.com:8080"
        
        url = f"https://www.shein.com/api/category/product/list?cat_id={cat_id}&page={page}&page_size=40&country={country}"
        
        resp = cffi_requests.get(
            url, headers=HEADERS,
            proxies={"http": proxy, "https": proxy},
            impersonate="chrome131", timeout=15
        )
        
        if resp.status_code == 200 and resp.json().get("code") == 0:
            products = resp.json()["data"]["products"]
            if not products:
                break  # 더 이상 상품 없음
            all_products.extend(products)
            time.sleep(random.uniform(1.5, 3.0))  # 자연스러운 간격
        elif resp.status_code == 412:
            time.sleep(5)  # _abck 갱신 대기
            continue
        else:
            time.sleep(2)
    
    return all_products

스티키 세션으로 통화 일관성 유지

한 국가의 전체 카탈로그를 수집하는 동안, 세션 ID를 고정하면 동일 IP가 유지됩니다. 하지만 너무 오래 유지하면 rate limit에 걸리므로, 페이지 5–10개마다 세션을 교체하는 것이 현실적입니다. 위 예제에서는 페이지마다 새 세션을 생성하지만, 같은 국가 코드를 유지하여 통화 일관성을 보장합니다.

412 / _abck 리프레시 로직

HTTP 412는 _abck 쿠키가 만료되었거나 검증에 실패했음을 의미합니다. 이 경우:

  1. 지수 백오프: 2초 → 4초 → 8초 대기 후 재시도
  2. 세션 ID 교체로 새 IP 확보
  3. 필요시 / 페이지를 먼저 방문하여 _abck 쿠키 재발급
  4. 3회 실패 시 해당 goods_id를 실패 큐에 추가하고 다음으로 진행

흔한 실수와 엣지 케이스

  • 데이터센터 프록시 사용: Akamai는 데이터센터 IP 대역을 사전에 식별하여 차단합니다. Shein 스크래핑에는 주거용 또는 모바일 프록시만 사용해야 합니다.
  • 세션 없이 로테이션: 요청마다 IP가 바뀌면, 첫 요청에서 USD로 설정된 통화가 뒤바뀔 수 있습니다. 항상 -session- 플래그를 사용하세요.
  • page_size 과도 설정: page_size=120 이상으로 설정하면 응답이 느려지거나 타임아웃이 발생합니다. 40–60이 안정적입니다.
  • smdeviceid 누락: API 요청 시 smdeviceid 헤더가 누락되면 간헐적으로 403이 반환됩니다. 디바이스 토큰 풀을 유지하고 세션별로 일관된 값을 사용하세요.
  • robots.txt 무시: Shein의 robots.txt를 확인하여 허용된 경로만 수집하는 것이 권장됩니다.

ProxyHat 설정 및 내부 링크

ProxyHat 대시보드(dashboard.proxyhat.com)에서 주거용 프록시 인증 정보를 확인할 수 있습니다. 프록시 가격 페이지에서 트래픽 요금제를 확인하고, 프록시 위치 페이지에서 지원 국가 목록을 볼 수 있습니다.

더 자세한 프록시 설정 방법은 ProxyHat 공식 문서를 참조하세요. Shein 외에도 다른 이커머스 플랫폼 스크래핑은 웹 스크래핑 사용 사례 페이지에서, 검색 엔진 결과 추적은 SERP 추적 사용 사례 페이지에서 확인할 수 있습니다.

윤리 및 이용약관 고려사항

공개 상품 데이터만 수집하세요. 가격, 재고, 상품명, 이미지 URL은 공개 정보이지만, 체크아웃 프로세스나 사용자 계정 데이터에 접근하는 것은 Shein 이용약관 위반이며, 미국의 CFAA(Computer Fraud and Abuse Act) 및 EU의 GDPR과 충돌할 수 있습니다.

  • 수집 속도 제한: 분당 30–50 요청을 초과하지 마세요. Shein 서버에 부하를 주는 것은 비윤리적이며 법적 리스크를 증가시킵니다.
  • 개인정보 수집 금지: 사용자 리뷰의 작성자 이름, 이메일, 위치 등 PII(개인식별정보)는 GDPR 대상입니다. 리뷰 텍스트만 수집하고 작성자 정보는 마스킹하세요.
  • 계정/체크아웃 접근 금지: 로그인, 결제, 주문 생성 API는 절대 스크래핑하지 마세요.

공식 제휴 피드가 더 나은 선택인 경우

Shein은 Shein Affiliate Program을 통해 제휴 파트너에게 상품 데이터 피드를 제공합니다. 대규모 가격 비교 사이트나 어필리에이트 플랫폼을 운영한다면, API 스크래핑 대신 공식 피드를 사용하는 것이 더 안정적이고 법적으로 안전합니다. 다만, 공식 피드는 실시간 재고 데이터가 지연될 수 있으며, 모든 국가의 가격이 포함되지 않을 수 있습니다.

핵심 요약 (Key Takeaways)

  • API 우선, HTML 폴백: /api/productInfo 엔드포인트가 HTML 파싱보다 효율적이지만, productIntroData JSON 블롭을 백업으로 사용하세요.
  • Akamai Bot Manager가 핵심 장벽: _abck 쿠키, sensor_data, smdeviceid 토큰을 모두 처리해야 합니다. curl_cffi로 TLS 지문을 모방하는 것이 필수입니다.
  • 주거용 프록시 + 지역 타겟팅 필수: Shein은 국가별로 가격·통화·재고를 현지화하므로, -country-US / -country-DE 플래그로 정확한 시장 데이터를 수집하세요.
  • 스티키 세션으로 통화 일관성: -session- 플래그로 동일 IP를 유지하여, 수집 도중 통화가 바뀌는 것을 방지하세요.
  • 분당 30–50 요청 이하: 이를 초과하면 412/403이 발생합니다. 지수 백오프와 세션 교체로 대응하세요.
  • 공개 데이터만, 윤리 준수: CFAA/GDPR 리스크를 피하기 위해 체크아웃/계정 접근을 피하고, 공식 제휴 피드를 대안으로 검토하세요.

FAQ

대규모 Shein 스크래핑이란 무엇인가요?

대규모 Shein 스크래핑은 Shein의 카탈로그, 가격, 재고 데이터를 수천~수만 개 단위로 자동 수집하는 작업을 의미합니다. 2026년 기준으로는 단순 HTML 파싱을 넘어 내부 API 엔드포인트 활용, Akamai Bot Manager 우회, 주거용 프록시 로테이션, 세션 스티키 관리가 필수 요소입니다. 패션 가격 인텔리전스 팀이 경쟁사 가격 모니터링, 트렌드 분석, 재고 추적을 위해 수행합니다.

왜 대규모 Shein 스크래핑에 프록시가 필요한가요?

Shein은 Akamai Bot Manager로 IP당 요청 빈도를 제한하며, 단일 IP로 분당 30–50개 이상 요청 시 412/403 응답을 반환합니다. 또한 국가별로 가격·통화·재고가 다르므로, 정확한 시장 데이터를 수집하려면 지역 타겟팅이 가능한 주거용 프록시가 필요합니다. 데이터센터 IP는 Akamai가 사전 식별하여 차단하므로 사용할 수 없습니다.

Shein 스크래핑에 어떤 프록시 유형이 가장 적합한가요?

주거용(Residential) 프록시가 가장 적합합니다. 실제 ISP IP를 사용하므로 Akamai의 데이터센터 IP 차단을 우회할 수 있고, 국가·도시 단위 지역 타겟팅이 가능합니다. 모바일 프록시도 좋은 대안이며, 4G/5G IP는 신뢰도가 높아 rate limit이 약간 더 관대합니다. 데이터센터 프록시는 Akamai에 즉시 차단되므로 권장하지 않습니다.

Shein 스크래핑 시 차단을 피하려면 어떻게 해야 하나요?

첫째, curl_cffi로 Chrome TLS 지문을 모방하세요. 둘째, 주거용 프록시로 분당 30–50 요청 이하로 유지하며, -session- 플래그로 스티키 세션을 사용하세요. 셋째, 412 응답 시 지수 백오프(2초→4초→8초) 후 세션을 교체하고 재시도하세요. 넷째, smdeviceid 디바이스 토큰을 세션별로 일관되게 유지하고, 자연스러운 요청 간격(1.5–3초)을 유지하세요.

Shein 공식 제휴 피드와 스크래핑 중 어떤 것을 선택해야 하나요?

실시간 재고와 다국가 가격 데이터가 필요하면 스크래핑이 유리합니다. 반면, 안정성과 법적 안전성이 최우선이고 실시간성이 덜 중요하면 공식 제휴 피드가 더 적합합니다. 많은 팀은 공식 피드를 기본으로 사용하면서, 실시간 가격 변동이나 특정 국가 데이터가 필요한 카테고리만 스크래핑으로 보완하는 하이브리드 방식을 사용합니다.

자주 묻는 질문

대규모 Shein 스크래핑이란 무엇인가요?

대규모 Shein 스크래핑은 Shein의 카탈로그, 가격, 재고 데이터를 수천~수만 개 단위로 자동 수집하는 작업을 의미합니다. 2026년 기준으로는 단순 HTML 파싱을 넘어 내부 API 엔드포인트 활용, Akamai Bot Manager 우회, 주거용 프록시 로테이션, 세션 스티키 관리가 필수 요소입니다. 패션 가격 인텔리전스 팀이 경쟁사 가격 모니터링, 트렌드 분석, 재고 추적을 위해 수행합니다.

왜 대규모 Shein 스크래핑에 프록시가 필요한가요?

Shein은 Akamai Bot Manager로 IP당 요청 빈도를 제한하며, 단일 IP로 분당 30–50개 이상 요청 시 412/403 응답을 반환합니다. 또한 국가별로 가격·통화·재고가 다르므로, 정확한 시장 데이터를 수집하려면 지역 타겟팅이 가능한 주거용 프록시가 필요합니다. 데이터센터 IP는 Akamai가 사전 식별하여 차단하므로 사용할 수 없습니다.

Shein 스크래핑에 어떤 프록시 유형이 가장 적합한가요?

주거용(Residential) 프록시가 가장 적합합니다. 실제 ISP IP를 사용하므로 Akamai의 데이터센터 IP 차단을 우회할 수 있고, 국가·도시 단위 지역 타겟팅이 가능합니다. 모바일 프록시도 좋은 대안이며, 4G/5G IP는 신뢰도가 높아 rate limit이 약간 더 관대합니다. 데이터센터 프록시는 Akamai에 즉시 차단되므로 권장하지 않습니다.

Shein 스크래핑 시 차단을 피하려면 어떻게 해야 하나요?

첫째, curl_cffi로 Chrome TLS 지문을 모방하세요. 둘째, 주거용 프록시로 분당 30–50 요청 이하로 유지하며, -session- 플래그로 스티키 세션을 사용하세요. 셋째, 412 응답 시 지수 백오프(2초→4초→8초) 후 세션을 교체하고 재시도하세요. 넷째, smdeviceid 디바이스 토큰을 세션별로 일관되게 유지하고, 자연스러운 요청 간격(1.5–3초)을 유지하세요.

Shein 공식 제휴 피드와 스크래핑 중 어떤 것을 선택해야 하나요?

실시간 재고와 다국가 가격 데이터가 필요하면 스크래핑이 유리합니다. 반면, 안정성과 법적 안전성이 최우선이고 실시간성이 덜 중요하면 공식 제휴 피드가 더 적합합니다. 많은 팀은 공식 피드를 기본으로 사용하면서, 실시간 가격 변동이나 특정 국가 데이터가 필요한 카테고리만 스크래핑으로 보완하는 하이브리드 방식을 사용합니다.

차단 없이 가격과 경쟁사를 추적하세요

이커머스 데이터를 위한 안정적인 주거용 프록시. 가입하고 깨끗한 데이터를 수집하세요.

시작하기
← 블로그로 돌아가기