헤드리스 브라우저 감지: 원인과 해결법 (2026)
사이트에서 "headless browser detected" 메시지가 뜨거나, 자동화된 브라우저에만 다른 페이지를 조용히 보여주는 경우가 있습니다. 헤드리스 브라우저는 창 없이 실행되고, 일반 데스크톱 브라우저와 미세하지만 측정 가능한 차이가 있기 때문입니다. 이 가이드는 사이트가 어떤 신호를 보는지, 내 브라우저가 무엇을 노출하고 있는지 진단하는 방법, 그리고 올바른 해결책이 무엇인지 설명합니다. 또한 멈춰야 하거나 그 검사를 captcha 단계로 취급해야 하는 지점도 다룹니다.
사이트가 헤드리스 브라우저를 확인하는 이유
자동화 프레임워크는 실제 브라우저 엔진을 구동하므로 페이지 대부분은 똑같이 동작합니다. 차이는 가장자리에서 드러납니다.
- 자동화 플래그. 자동화 도구로 구동되는 브라우저는 과거에
navigator.webdriver속성이true로 설정되어 노출되었고, 일부 프레임워크는 페이지에 다른 흔적을 남깁니다. - 없거나 이상한 브라우저 기능. 헤드리스 빌드는 플러그인이 없거나, 언어 목록이 특이하거나, 실제 화면과 맞지 않는 창 크기를 보고할 수 있습니다.
- 렌더링 차이. Canvas와 WebGL 출력은 헤드리스와 헤디드 환경 사이에서 다를 수 있으며, 특히 GPU가 없는 서버에서 그렇습니다.
- 타이밍. 자동화된 클릭과 페이지 로드는 사람이라면 만들지 않을 리듬으로 일어나는 경우가 많습니다.
- 네트워크 동작. 요청 헤더, 헤더 순서, TLS 핸드셰이크가 브라우저가 아닌 클라이언트를 드러낼 수 있습니다.
사이트는 이런 신호를 조합해 점수를 매깁니다. 점수가 낮으면 조용한 다운그레이드, 추가 검사, 또는 차단으로 이어질 수 있습니다.
1단계: 브라우저가 무엇을 노출하는지 확인하기
무엇이든 바꾸기 전에, 페이지가 자동화 브라우저에서 무엇을 읽을 수 있는지 살펴보세요. 아래 스크립트는 직접 관리하는 페이지를 열고 중요한 신호를 출력합니다. 이것은 진단용이며, 다른 사람의 시스템을 탐색하는 용도로 쓰지 마세요.
from playwright.sync_api import sync_playwright
CHECK = """() => ({
webdriver: navigator.webdriver,
languages: navigator.languages,
plugins: navigator.plugins.length,
userAgent: navigator.userAgent,
screen: [screen.width, screen.height],
viewport: [window.innerWidth, window.innerHeight],
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
})"""
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com") # 직접 소유한 페이지로 바꾸세요
print(page.evaluate(CHECK))
browser.close()
같은 스크립트를 headless=False로 실행한 뒤 두 출력을 비교하세요. 그 차이가 사이트가 알아챌 수 있는 부분입니다.
2단계: 플래그가 아니라 불일치를 고치기
플래그 하나만 숨기고 나머지는 그대로 두는 것이 가장 흔한 실수입니다. User agent는 Windows라고 말하는데 폰트, 타임존, 화면 크기는 Linux 서버를 가리키면, 속성 하나보다 훨씬 강한 신호가 됩니다. 내부적으로 일관된 환경을 목표로 하세요.
- 가능하면 헤디드 브라우저를 쓰거나, 최신 데스크톱 브라우저와 맞는 헤드리스 모드를 쓰세요.
- 뷰포트와 언어를 서로 맞추세요.
- 타임존과 로케일을 사용하는 IP 주소와 일치시키세요.
- 실행할 때마다 새로 시작하지 말고, 하나의 신원에는 하나의 프로필과 쿠키를 재사용하세요.
Playwright에서는 이런 설정 여러 개를 한곳에서 지정할 수 있습니다.
context = browser.new_context(
locale="en-US",
timezone_id="America/New_York",
viewport={"width": 1366, "height": 768},
)
page = context.new_page()
3단계: 속도를 줄이고 방문자처럼 행동하기
자동화는 사람이 할 수 있는 속도보다 빠를 때 바로 티가 납니다. 페이지 로드 사이에 현실적인 간격을 두고, 같은 요소를 완벽한 리듬으로 반복 클릭하지 마세요. 한 주소에서 수백 개의 페이지를 동시에 열지도 마세요. 요청을 적게, 천천히 보내면 사이트의 부담도 줄어들며, 이는 어차피 올바른 행동입니다.
4단계: 그 검사가 captcha인지 알아보기
일부 감지 흐름은 차단 대신 챌린지로 끝납니다. captcha 위젯이 보이면, 그 단계는 솔버에서 받은 토큰이 필요합니다. 현재 Scarnox에서 실제로 제공되는 captcha 유형은 PopularCaptcha입니다. PopularCaptcha Python 가이드에서 토큰을 요청하고 제출하는 방법을 확인할 수 있습니다. Cloudflare Turnstile 같은 다른 위젯은 로드맵에 있지만 아직 제공되지 않으니, 계획을 세우기 전에 captcha 유형 설명을 확인하세요.
captcha 단계가 나왔다고 해서 나머지 설정이 올바르다는 뜻은 아닙니다. 설정을 어떻게 바꿔도 같은 사이트가 헤드리스 세션을 계속 차단한다면, 소유자가 자동화된 접근을 원하지 않는다는 명확한 신호입니다. 그 뜻을 존중하세요.
하지 말아야 할 것
접근을 금지한 사이트에서 자동화를 숨기려 하지 마세요. 감지 우회 도구를 써서 접근 제어를 뚫지도 마세요. 그것은 이 가이드가 다루는 테스트와 공개 데이터 수집과는 다른 종류의 프로젝트입니다. 프로젝트에 필요한 접근 권한이 없다면, 사이트 소유자에게 문의하거나 공식 API 또는 데이터 피드를 찾아보세요.
책임 있는 스크래핑
- 자동화하기 전에 사이트의
robots.txt와 이용 약관을 확인하세요. - 요청 빈도를 낮게 유지하고, 이미 가져온 페이지는 캐시하세요.
- 차단은 우회해야 할 퍼즐이 아니라 하나의 답으로 받아들이세요.
- 적법한 근거 없이 개인 데이터를 수집하지 마세요.
다음으로 할 일
자동화가 end-to-end 테스트를 위한 것이라면 접근 방식이 다릅니다. 자동화 테스트에서의 captcha를 참고하세요. Playwright나 Puppeteer로 구성하고 있다면, Playwright와 Puppeteer에서의 captcha 처리에서 토큰을 어디에 넣는지 설명합니다.
무료 체험 크레딧으로 시작하세요. 카드 없이 가능합니다. 계정을 만들고 직접 소유한 페이지에서 PopularCaptcha 흐름을 테스트해 보세요. 현재 요금은 요금 페이지에서 확인할 수 있습니다.