탐지 없이 web scraping 하기: Clawbrowser 글 커버 이미지

탐지 없이 web scraping 하기: 실전에서 버티는 기법

Clawbrowser Teamweb-scrapinganti-botfingerprintingproxyguide

scraper는 첫 실행에서는 잘 동작합니다. 세 번째 실행쯤에는 403, 빈 response, CAPTCHA loop가 나옵니다. 코드는 그대로입니다. 사이트도 그대로입니다. anti-bot 시스템이 session profile을 만들고 차단하기 시작한 것입니다.

TL;DR: 대부분의 차단은 network, browser identity, behavior, session state 네 계층에서 발생합니다. fingerprints와 proxy routing을 engine 수준에서 관리하는 anti-detect browser로 시작하고, 코드는 recon, extraction, pagination, scale에 집중하게 합니다.

네 계층 모델 전체는 다음 글에서 다룹니다: 차단 없는 browser automation: 4계층 방어 스택.


코드 전에 사전 조사

바로 scraper를 쓰면 다시 만들 가능성이 큽니다. 10분만 조사해도 올바른 stack을 고를 수 있습니다.

anti-bot 시스템 확인

대상 사이트에서 DevTools를 열고 response headers를 확인합니다.

Header anti-bot 시스템
cf-ray, server: cloudflare Cloudflare Bot Management
x-akamai-transformed Akamai Bot Manager
x-datadome DataDome
x-px-* headers PerimeterX (now HUMAN)
해당 없음 상용 anti-bot이 없거나 자체 솔루션일 가능성

보호가 약한 사이트는 curl_cffi로 충분합니다. Cloudflare 사이트는 managed fingerprints가 있는 실제 browser가 필요합니다.

API가 있는지 확인

browser scraper를 만들기 전에 Network에서 XHR/Fetch를 봅니다. 많은 사이트가 JSON endpoint로 데이터를 로드합니다.

# If the site loads product data from an API endpoint
from curl_cffi import requests

response = requests.get(
    "https://target-site.com/api/v2/products?category=electronics&page=1",

endpoint는 빠르지만, 보호된 사이트는 실제 browser session 이후의 API call을 기대할 수 있습니다. 그때는 page를 browser로 로드하고 response를 intercept합니다.

rendering model 평가

JavaScript를 끕니다. content가 남아 있으면 HTTP로 충분합니다. 빈 페이지면 browser engine이 필요합니다.

JS 없이 content가 보이나요? 도구
예, 모두 렌더링됨 curl_cffi or requests with TLS impersonation
일부만 curl_cffi for static parts, browser for dynamic
아니요, 빈 페이지 Full browser (Clawbrowser + Playwright/Puppeteer)

scraping stack 선택

도구는 보호 수준과 rendering model에 따라 달라집니다. HTTP면 충분한데 full browser를 쓰면 리소스 낭비이고, 보호된 SPA에 HTTP만 쓰면 시간이 낭비됩니다.

의사결정 트리

anti-bot 없음 + server-rendered HTML: curl_cffi와 TLS impersonation을 사용합니다.

from curl_cffi import requests

response = requests.get(
    "https://unprotected-site.com/products",
    impersonate="chrome136"

anti-bot 없음 + JavaScript-rendered: 일반 headless browser를 사용합니다.

anti-bot + server-rendered HTML: curl_cffi와 residential proxy를 사용합니다.

anti-bot + JavaScript-rendered: managed fingerprints와 residential proxy가 있는 Clawbrowser를 사용합니다.

from playwright.async_api import async_playwright

async def scrape_protected_site():
    async with async_playwright() as p:
        # Clawbrowser handles fingerprints, TLS and proxy at the engine level

Clawbrowser는 local, free, Chromium 기반 anti-detect browser이며 managed fingerprints, proxy routing, native CDP, built-in MCP server를 제공합니다.


데이터 추출 패턴

anti-bot 계층을 지나면 안정적으로 structured data를 추출하는 일이 남습니다.

Pagination

pagination은 보통 세 가지 형태입니다.

URL 기반 pagination

async def scrape_paginated(page, base_url, max_pages=50):
    all_items = []
    for page_num in range(1, max_pages + 1):
        await page.goto(f"{base_url}?page={page_num}")
        await human_delay(2000, 4000)

Infinite scroll (scroll 시 content 로드):

async def scrape_infinite_scroll(page, max_scrolls=30):
    all_items = []
    previous_count = 0

    for _ in range(max_scrolls):

"Load more" button:

async def scrape_load_more(page):
    while True:
        load_more = await page.query_selector('[data-testid="load-more"]')
        if not load_more:
            break

동적 content 처리

일부 데이터는 click, accordion, hover 뒤에만 나타납니다.

async def extract_product_details(page, product_url):
    await page.goto(product_url)
    await human_delay(1000, 2000)

    # Click "Specifications" tab to reveal hidden data

shadow DOM에서 추출

shadow DOM 안의 component는 shadow root를 통해 읽어야 합니다.

# Pierce through shadow DOM to extract data
data = await page.evaluate("""
    () => {
        const host = document.querySelector('product-card');
        const shadow = host.shadowRoot;

scraping session 관리

scraper는 사람보다 훨씬 많은 page를 봅니다. session이 일관되게 보여야 합니다.

Session warming

target page로 바로 가지 말고 home, category, cookie banner를 거친 뒤 scrape합니다. behavior 계층은 차단 없는 browser automation: 4계층 방어 스택.

async def warm_session(page, site_url):
    await page.goto(site_url)
    await human_delay(2000, 4000)

    # Accept cookies if banner appears

scale에서 profile rotation

대량 작업은 여러 Clawbrowser profiles에 나눕니다. 각 profile은 fingerprint, cookies, storage, proxy를 따로 가집니다.

import asyncio
from playwright.async_api import async_playwright

async def scrape_batch(profile_name, urls):
    async with async_playwright() as p:
규모 권장 방식
< 100 pages/day Single profile, residential proxy, 3-5s delays
100-1,000 pages/day 3-5 rotating profiles, sticky residential sessions
1,000-10,000 pages/day 10+ profiles, proxy pool, session warming
10,000+ pages/day Distributed setup, multiple Clawbrowser instances, backoff logic

차단 진단

증상은 대개 실패한 계층을 알려줍니다.

증상 가능한 원인 해결
첫 request에서 차단 IP reputation 또는 browser fingerprint residential proxy와 anti-detect browser 사용
5-10 page 후 차단 behavior detection 또는 session limit 속도 낮추기, delay 추가, session warming
CAPTCHA on every page Fingerprint leak Browser is leaking automation signals, switch to managed fingerprints
403 after proxy rotation Browser fingerprint unchanged New IP but same broken fingerprint, fix the browser layer
local은 성공, production은 실패 Datacenter IP production에 residential proxy 추가
빈 페이지 / 무한 spinner JavaScript challenge failed Browser can't pass Cloudflare/Akamai JS check, needs real engine
수동 방문과 데이터가 다름 Geo or locale mismatch Proxy location doesn't match fingerprint timezone/language

빠른 진단 script

import asyncio
from playwright.async_api import async_playwright

async def diagnose_blocking(target_url):
    async with async_playwright() as p:

Cloudflare 보호 사이트 scraping

Cloudflare는 TLS, JavaScript, behavior, IP reputation을 동시에 봅니다.

Cloudflare가 확인하는 것

  1. TLS fingerprint (JA3/JA4): ClientHello가 맞지 않으면 HTML 전에 challenge가 나옵니다.
  2. JavaScript execution: Turnstile은 실제 rendering engine을 요구합니다.
  3. IP reputation: IP reputation은 수많은 사이트에서 평가됩니다.
  4. Request patterns: 같은 session의 반복 request pattern은 빠르게 flag됩니다.

workflow

모든 계층을 동시에 정리합니다. TLS/JS는 anti-detect browser, IP는 residential proxy, timing은 code에서 담당합니다.

async def scrape_cloudflare_site(target_url, profile="cf-scraper"):
    async with async_playwright() as p:
        browser = await p.chromium.connect_over_cdp(
            f"http://127.0.0.1:9222?profile={profile}"
        )

Cloudflare 상세 내용은 Playwright scripts가 Cloudflare에 계속 막히는 이유.


AI agent scraping

Clawbrowser MCP server를 쓰면 AI agent가 CDP로 실제 browser session을 제어합니다. fingerprints와 proxy routing은 코드에서 실행할 때와 같습니다.

전체 통합 가이드는 AI agent용 CDP browser: 개발자 가이드.


FAQ

왜 scraper가 local에서는 되는데 production에서는 실패하나요?

local은 보통 residential IP이고 production은 datacenter IP입니다. residential proxy를 추가하고 managed fingerprints를 확인합니다.

HTTP client와 browser 중 무엇을 써야 하나요?

server-rendered HTML이고 anti-bot이 없으면 HTTP면 됩니다. JavaScript rendering이나 challenge가 있으면 full browser를 씁니다.

Cloudflare 사용 여부는 어떻게 알 수 있나요?

DevTools response headers에서 cf-ray 또는 server: cloudflare를 찾습니다.

proxies 없이 scrape할 수 있나요?

보호 없는 사이트는 가능합니다. Cloudflare/Akamai 뒤나 scale 작업에서는 보통 residential proxies가 필요합니다.


탐지 없이 web scraping 시작하기

안정적인 scraping은 사전 조사, 맞는 도구, 깨끗한 browser infrastructure에서 시작합니다.

Install Clawbrowser 로 browser identity와 network 계층을 처리합니다. 설치 prompt를 clawbrowser.ai 에서 복사해 AI agent에 붙여넣으면 됩니다. setup은 2분 이내입니다.

detection model은 차단 없는 browser automation: 4계층 방어 스택. fingerprinting 상세는 Browser fingerprinting: anti-bot 시스템이 보는 20개 이상의 신호.

Continue exploring

Ask AI how Clawbrowser helps

계속 읽기

모든 글 보기 →