PerimeterX (HUMAN) 이해하기: 탐지 신호와 합법적 우회 가이드

PerimeterX(현 HUMAN Security)의 _px3 쿠키, 디바이스 핑거프린팅, TLS/JA3, 행동 분석 신호를 깊이 있게 분석하고, 주거 프록시와 Playwright 스텔스로 합법적으로 우회하는 실전 방법을 다룹니다.

Understanding PerimeterX (HUMAN): Detection Signals, Architecture & Legitimate Bypass

PerimeterX (HUMAN) 이해하기: 왜 이렇게 강력한가

PerimeterX (HUMAN) 이해하기를 검색하는 분들은 대부분 이미 _px3 쿠키와 만나본 적이 있을 것입니다. 항공사 티켓 수집, 럭셔리 이커머스 가격 모니터링, SERP 트래킹 중 갑자기 403 Forbidden과 함께 captcha-delivery.com 스크립트가 로드되는 경험 — 이것이 PerimeterX의 전형적인 차단 시그니처입니다. PerimeterX는 2020년 HUMAN Security와 합병하여, 단순 IP 평판 기반 WAF에서 벗어나 행동 신호(behavioral signals)에 크게 의존하는 봇 관리 플랫폼으로 진화했습니다.

PerimeterX가 다른 봇 방어 솔루션과 다른 점은, IP 평판과 단순 헤더 검증을 넘어 마우스 이동 패턴, 키보드 타이밍, 스크롤 속도 같은 행동 생체신호를 실시간으로 분석한다는 점입니다. 이는 스크래핑 엔지니어에게 단순한 헤더 회전이나 IP 로테이션만으로는 부족하다는 것을 의미합니다. 이 글에서는 PerimeterX의 아키텍처와 탐지 신호를 기술적으로 분해한 뒤, HUMAN Security의 시스템을 합법적으로 통과하기 위한 구체적 구현 방법을 제시합니다.

PerimeterX 아키텍처: _px3, _pxhd 쿠키와 JS 챌린지 흐름

PerimeterX의 핵심은 클라이언트 측 JavaScript 센서가 수집한 데이터를 서버로 전송해 위험 점수(risk score)를 산출하는 구조입니다. 이 과정에서 두 개의 핵심 쿠키가 사용됩니다.

_px 쿠키 군: _px3, _pxhd, _px2

  • _px3: 메인 세션 쿠키. 센서가 수집한 디바이스/행동 데이터를 인코딩한 페이로드를 담습니다. Base64 변형 인코딩이 적용되며, 내부에 캔버스 핑거프린트, WebGL 렌더러 정보, 화면 해상도, 타임존, 폰트 목록 등이 포함됩니다.
  • _pxhd: _px3와 페어링되는 영구 식별자. 봇이 쿠키를 삭제하고 재시도해도 서버 측에서 재발급 시점의 패턴을 교차 검증할 수 있습니다.
  • _px2: 구버전 쿠키. 현재는 대부분 _px3로 대체되었으나 일부 레거시 배포에서 잔존합니다.

JS 챌린지 흐름은 대략 다음과 같습니다: 페이지 로드 시 window._pxAppId가 설정되고, 센서 스크립트가 로드되어 디바이스 데이터를 수집한 뒤 /px/init 엔드포인트로 페이로드를 POST합니다. 서버는 점수를 계산하고, 위험도가 임계치를 초과하면 CAPTCHA 챌린지 또는 블록 페이지를 반환합니다. 이때 _px3 쿠키가 갱신되며, 이후 요청은 갱신된 쿠키를 제시해야 정상 응답을 받습니다.

PerimeterX 탐지 신호: 4가지 핑거프린팅 계층

PerimeterX 탐지는 단일 신호에 의존하지 않습니다. 여러 신호를 조합해 점수를 매기며, 각 계층을 이해하는 것이 우회의 출발점입니다.

1. 디바이스 핑거프린팅 — Canvas, WebGL, 화면 메트릭

PerimeterX 센서는 HTMLCanvasElement.getContext('2d')를 호출해 Canvas API로 렌더링한 뒤, 픽셀 데이터 해시를 추출합니다. 이 해시는 GPU, 드라이버, 폰트 렌더링 설정에 따라 달라져 디바이스 식별에 사용됩니다. WebGL 렌더러 문자열(UNMASKED_RENDERER_WEBGL), 화면 해상도(screen.width, screen.height), window.devicePixelRatio, 사용 가능 폰트 목록도 함께 수집됩니다.

Playwright/Puppeteer의 기본 헤드리스 환경은 Canvas 해시가 일관되게 동일하게 나타나며, navigator.webdrivertrue로 노출되어 즉시 탐지됩니다. 또한 화면 해상도가 0x0이거나 폰트 목록이 비정상적으로 적으면 핑거프린트 불일치로 플래그됩니다.

2. TLS/JA3 핑거프린트

PerimeterX는 클라이언트의 TLS ClientHello에서 JA3 핑거프린트를 추출합니다. JA3는 CipherSuites 목록, 확장 필드 순서, 타원 곡선 그룹을 해시화한 값으로, Python requests의 기본 OpenSSL 스택과 Chrome의 BoringSSL 스택은 서로 다른 JA3를 생성합니다. requests로 PerimeterX 보호 사이트에 접근하면, 헤더를 완벽히 위장해도 JA3가 Chrome이 아닌 Python의 것이면 탐지됩니다.

JA4는 JA3의 후속으로, Application-Layer Protocol(ALPN)과 SNI 존재 여부를 추가로 인코딩합니다. PerimeterX의 최신 배포는 JA3와 JA4를 모두 수집하는 것으로 관찰됩니다.

3. IP 평판과 프록시 탐지

IP 신호는 전통적이지만 여전히 중요합니다. PerimeterX는 ASN 데이터베이스, 데이터센터 IP 대역, 과거 악성 행동 이력을 교차 검증합니다. 데이터센터 IP(AWS, DigitalOcean, Hetzner 대역)에서 들어오는 요청은 기본 점수가 높게 시작합니다. 반면 주거 ISP IP는 신뢰 점수가 높아 초기 차단 확률이 낮습니다. 이것이 주거 프록시가 PerimeterX 우회의 기본 전제가 되는 이유입니다.

4. 행동 신호 — 마우스, 키보드, 타이밍

PerimeterX가 DataDome이나 Akamai와 차별화되는 지점입니다. 센서는 mousemove, click, keydown 이벤트의 타임스탬프와 좌표를 수집해 행동 프로파일을 만듭니다. 직선적 마우스 이동, 일정한 간격의 클릭, 0ms 간 타이밍은 봇 신호로 처리됩니다. 인간은 마우스를 곡선으로 움직이고, 클릭 간 200ms~500ms의 불규칙 간격을 보이며, 페이지 체류 시간에 분산이 있습니다.

PerimeterX vs DataDome vs Akamai: 비교

세 솔루션은 모두 봇 관리 시장의 주요 플레이어지만, 탐지 철학이 다릅니다. 아래 표는 각 솔루션의 주요 신호 가중치를 비교한 것입니다.

특성PerimeterX (HUMAN)DataDomeAkamai Bot Manager
주요 탐지 축행동 신호 + 디바이스 핑거프린트IP 평판 + 헤더 일관성JS 센서 복잡도 + TLS 핑거프린트
쿠키 구조_px3, _pxhddatadome, datadome_iud_abck, bm_sz, ak_bmsc
행동 분석 가중치매우 높음중간중간~높음
JA3/JA4 의존도중간중간높음
챌린지 방식CAPTCHA + JS 퍼즐CAPTCHA + JS 퍼즐센서 데이터 재전송 루프
주거 프록시 효과높음 (IP 점수 상쇄)높음높음

핵심 차이: Akamai는 _abck 쿠키를 갱신하는 센서 재전송 루프가 복잡해 난독화된 JS를 역분석해야 하는 반면, PerimeterX는 행동 신호 비중이 더 높아 실제 브라우저 환경에서 인간처럼 행동하는 것이 더 중요합니다. DataDome은 IP/헤더 일관성 검증이 강해, 프록시 풀 품질과 헤더 정합성이 핵심입니다.

PerimeterX를 사용하는 사이트

PerimeterX는 항공사와 럭셔리 이커머스에서 두드러집니다. 실제 배포가 관찰된 대표 사이트는 다음과 같습니다.

  • 항공사: United Airlines, American Airlines, Delta Air Lines — 항공권 가격 스크래핑 방지 목적.
  • 럭셔리 이커머스: Neiman Marcus, Saks Fifth Avenue — 한정판/가격 모니터링 봇 차단.
  • 기타: 일부 티켓팅 플랫폼, 스니커즈 리셀 사이트 일부.

이 사이트들은 가격 변동이 빠르고 경쟁 스크래핑이 집중되는 특성상 봇 방어 투자가 큽니다. 항공사의 경우, 가격 비교 사이트를 위한 공식 API 대신 비공식 스크래핑을 차단하려는 의도가 강합니다.

합법적 우회 실전: 주거 프록시 + Playwright 스텔스 + 행동 패턴

여기서 '우회'란 허가받은 보안 연구, 자사 데이터 수집, 또는 사이트 이용약관을 준수하는 합법적 자동화 범위 내에서 차단을 회피하는 기술적 구현을 의미합니다. 타인의 사이트를 무단 스크래핑하는 것은 별개의 법적/윤리적 문제입니다.

핵심 원칙

  1. 진짜 브라우저 사용: 헤드리스 Chromium을 스텔스 플러그인으로 위장. requests + 헤더 위조만으로는 JA3와 행동 신호에서 탈락.
  2. 주거 프록시: 데이터센터 IP는 PerimeterX 초기 점수가 이미 높음. 주거 ISP IP로 시작점을 정상화.
  3. 행동 시뮬레이션: 마우스 곡선 이동, 클릭 간 200ms~800ms 무작위 간격, 페이지 체류 시간 분산.
  4. 속도 제한: 초당 1~2 요청 이하, 세션당 50~100 요청 후 교체.

코드 예제 1: curl로 주거 프록시 기본 연결 확인

먼저 ProxyHat 주거 프록시가 정상 작동하는지 확인합니다. 미국 IP로 geo-targeting을 지정합니다.

curl -x http://user-country-US:YOUR_PASSWORD@gate.proxyhat.com:8080 \
  -s -o /dev/null -w "%{http_code} %{time_total}s\n" \
  https://www.united.com/

정상 주거 IP라면 200 또는 챌린지 페이지의 403이 아닌 정상 응답 코드를 받아야 합니다. time_total이 200ms~800ms 범위면 지연도 정상입니다.

코드 예제 2: Playwright 스텔스 + 주거 프록시 (Python)

다음은 Playwright의 playwright-stealth 패턴과 ProxyHat 주거 프록시를 조합한 예제입니다. navigator.webdriver를 숨기고, 캔버스 핑거프린트에 미세 노이즈를 추가하며, 행동 패턴을 시뮬레이션합니다.

from playwright.sync_api import sync_playwright
import random, time

PROXY = "http://user-country-US-session-sess01:YOUR_PASSWORD@gate.proxyhat.com:8080"

def human_mouse_move(page, selector):
    box = page.locator(selector).bounding_box()
    if not box:
        return
    # 곡선 마우스 이동: 시작점에서 목표점까지 중간점을 거쳐 이동
    start_x, start_y = random.uniform(100, 400), random.uniform(100, 400)
    mid_x = (start_x + box['x']) / 2 + random.uniform(-50, 50)
    mid_y = (start_y + box['y']) / 2 + random.uniform(-50, 50)
    page.mouse.move(start_x, start_y)
    page.mouse.move(mid_x, mid_y, steps=random.randint(8, 20))
    page.mouse.move(box['x'] + box['width']/2, box['y'] + box['height']/2, steps=random.randint(10, 25))
    time.sleep(random.uniform(0.2, 0.6))
    page.mouse.click(box['x'] + box['width']/2, box['y'] + box['height']/2)

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=False,  # 디버깅 시 headless=False 권장
        proxy={"server": PROXY},
        args=["--disable-blink-features=AutomationControlled"]
    )
    context = browser.new_context(
        viewport={"width": 1920, "height": 1080},
        user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        locale="en-US",
        timezone_id="America/New_York"
    )
    # navigator.webdriver 숨김
    context.add_init_script("""
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        // Canvas 핑거프린트 미세 노이즈
        const origToDataURL = HTMLCanvasElement.prototype.toDataURL;
        HTMLCanvasElement.prototype.toDataURL = function(type) {
            const ctx = this.getContext('2d');
            if (ctx) {
                const imageData = ctx.getImageData(0, 0, this.width, this.height);
                for (let i = 0; i < imageData.data.length; i += 4) {
                    imageData.data[i] ^= 1; // R 채널 미세 변경
                }
                ctx.putImageData(imageData, 0, 0);
            }
            return origToDataURL.apply(this, arguments);
        };
    """)
    page = context.new_page()
    page.goto("https://www.example.com", wait_until="domcontentloaded")
    time.sleep(random.uniform(2.0, 4.0))  # 인간 체류 시간
    human_mouse_move(page, "a[href='/flights']")
    time.sleep(random.uniform(1.5, 3.0))
    content = page.content()
    print("_px3 present:", "_px3" in page.context.cookies())
    browser.close()

주의: headless=False는 디버깅용입니다. 프로덕션에서는 Xvfb 가상 디스플레이와 함께 headless=True + 스텔스 인젝션을 사용하세요. --disable-blink-features=AutomationControlled만으로는 부족하며, navigator.webdriver 재정의와 Canvas 노이즈 주입이 필수입니다.

코드 예제 3: Node.js로 속도 제한 및 세션 로테이션

PerimeterX는 세션당 요청 누적 점수를 매깁니다. 100개 이상 연속 요청 시 행동 점수가 임계치에 도달할 수 있습니다. 아래는 세션을 50 요청마다 교체하며, 요청 간 1.5~3초 무작위 지연을 적용하는 Node.js 패턴입니다.

const { chromium } = require('playwright');

const PASSWORD = 'YOUR_PASSWORD';
let sessionCounter = 0;
let requestCounter = 0;

function newProxySession() {
  sessionCounter++;
  return `http://user-country-US-session-sess${sessionCounter}:${PASSWORD}@gate.proxyhat.com:8080`;
}

function randomDelay(min, max) {
  return new Promise(r => setTimeout(r, (min + Math.random() * (max - min)) * 1000));
}

(async () => {
  let proxy = newProxySession();
  const browser = await chromium.launch({
    proxy: { server: proxy },
    args: ['--disable-blink-features=AutomationControlled']
  });
  const context = await browser.newContext({
    viewport: { width: 1920, height: 1080 },
    userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
  });
  await context.addInitScript("Object.defineProperty(navigator,'webdriver',{get:()=>undefined})");
  const page = await context.newPage();

  for (const url of targetUrls) {
    if (requestCounter >= 50) {
      await context.close();
      proxy = newProxySession();
      // 새 프록시 세션으로 컨텍스트 재생성 (실제 구현은 래핑 필요)
      requestCounter = 0;
    }
    await page.goto(url, { waitUntil: 'domcontentloaded' });
    await randomDelay(1.5, 3.0);
    // 마우스 스크롤 시뮬레이션
    await page.mouse.wheel(0, Math.floor(Math.random() * 300 + 100));
    await randomDelay(0.5, 1.5);
    requestCounter++;
  }
  await browser.close();
})();

이 패턴의 핵심은 세션 교체 주기요청 간 지연의 무작위성입니다. 일정한 2초 간격도 탐지될 수 있으므로, 지연은 반드시 무작위 분포를 따라야 합니다.

흔한 실수와 엣지 케이스

1. requests + 헤더 위조만 사용

가장 흔한 실수입니다. Python requests의 JA3는 Chrome과 다르므로, User-Agent를 Chrome으로 위장해도 TLS 핑거프린트에서 탈락합니다. 해결책은 curl_cffi 라이브러리로 Chrome의 TLS 핑거프린트를 모방하거나, Playwright를 사용하는 것입니다.

2. Canvas 핑거프린트 완전 제거

Canvas를 아예 비활성화하면 정상 브라우저와 너무 다름이 탐지됩니다. 정상 브라우저는 Canvas 해시를 반환하므로, 핑거프린트를 제거하기보다 미세 노이즈를 추가해 해시를 매 세션마다 다르게 만드는 것이 안전합니다.

3. 데이터센터 프록시 사용

AWS/GCP IP 대역에서 PerimeterX 보호 사이트에 접근하면 초기 점수가 이미 높습니다. 주거 프록시는 필수입니다. ProxyHat의 주거 프록시 풀은 전 세계 190개국 이상을 커버하며, ISP 진성 IP를 제공합니다.

4. 세션 쿠키 재사용

_px3 쿠키를 한 번 발급받은 뒤 여러 IP에서 재사용하면, IP-쿠키 불일치로 탐지됩니다. 세션과 IP는 1:1로 매핑되어야 하며, ProxyHat의 session- 플래그로 sticky 세션을 유지하세요.

ProxyHat 설정: 주거 프록시로 PerimeterX 통과하기

ProxyHat 주거 프록시는 PerimeterX 우회의 기반입니다. 게이트웨이 gate.proxyhat.com, HTTP 포트 8080, SOCKS5 포트 1080을 사용합니다.

연결 형식

  • HTTP: http://USERNAME:PASSWORD@gate.proxyhat.com:8080
  • SOCKS5: socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080
  • 미국 geo-targeting: http://user-country-US:PASSWORD@gate.proxyhat.com:8080
  • 도시 단위 타겟팅: http://user-country-US-city-newyork:PASSWORD@gate.proxyhat.com:8080
  • Sticky 세션: http://user-session-abc123:PASSWORD@gate.proxyhat.com:8080

자세한 연결 가이드는 ProxyHat 공식 문서를 참조하세요. 가격 정보는 프라이싱 페이지에서 확인할 수 있으며, 웹 스크래핑 및 SERP 트래킹 사용 사례는 각각 웹 스크래핑SERP 트래킹 페이지에서 확인할 수 있습니다.

윤리적 프레임: 합법적 스크래핑의 경계

기술적 우회 능력과 그 사용의 정당성은 분리되어야 합니다. PerimeterX 우회는 다음 조건에서 합법적일 수 있습니다:

  • 자사 데이터 수집: 자신이 소유하거나 명시적 권한이 있는 자산의 자동화.
  • 공식 API 우선: 사이트가 공식 API를 제공한다면 스크래핑 전에 API 사용을 먼저 검토.
  • robots.txt 준수: Robots Exclusion Standard를 확인하고 허용된 경로만 수집.
  • 속도 제한: 대상 서버에 부하를 주지 않는 요청 속도 (초당 1~2 요청 이하 권장).
  • 이용약관 검토: 사이트 ToS를 확인하고, 금지된 경우 스크래핑 중단.
  • 개인정보 보호: GDPR/CCPA 등 개인정보 보호법 준수, 개인 데이터 수집 최소화.

무단 스크래핑, 경쟁사 데이터 대량 수집, 서비스 거부 수준의 트래픽은 기술적으로 가능하더라도 윤리적/법적 문제가 있습니다. 이 글의 기술은 합법적 자동화와 보안 연구를 위한 것입니다.

핵심 요약 (Key Takeaways)

  • PerimeterX는 행동 신호(마우스, 키보드, 타이밍)에 가장 큰 가중치를 두는 봇 관리 플루트폼입니다. 단순 IP/헤더 회전만으로는 부족합니다.
  • _px3 쿠키는 Canvas, WebGL, 화면, 폰트 핑거프린트를 인코딩합니다. 이를 제거하기보다 미세 노이즈로 매 세션마다 변형하는 것이 안전합니다.
  • JA3/JA4 TLS 핑거프린트는 requests와 Chrome이 다릅니다. Playwright 또는 curl_cffi로 Chrome TLS를 모방하세요.
  • 데이터센터 IP는 초기 점수가 높습니다. ProxyHat 주거 프록시로 ISP 진성 IP를 사용해 시작 점수를 정상화하세요.
  • 요청 간 지연은 무작위 분포(1.5~3초)를 따르고, 세션당 50~100 요청 후 교체하세요.
  • 모든 우회는 사이트 ToS, robots.txt, 개인정보 보호법 준수 범위 내에서만 윤리적입니다.

PerimeterX는 강력하지만, 진짜 브라우저 + 주거 IP + 인간 행동 시뮬레이션의 조합으로 합법적 자동화 범위 내에서 통과할 수 있습니다. ProxyHat 주거 프록시로 시작하려면 프라이싱 페이지에서 플랜을 확인하세요.

시작할 준비가 되셨나요?

AI 필터링으로 148개국 이상에서 5천만 개 이상의 레지덴셜 IP에 액세스하세요.

가격 보기레지덴셜 프록시
← 블로그로 돌아가기