Python Selenium captcha 풀이: 동작하는 예제 (2026)
Selenium은 실제 브라우저를 실행하므로, 페이지가 렌더링되고 스크립트가 사람이 볼 때와 똑같이 실행됩니다. Selenium이 할 수 없는 유일한 단계는 PopularCaptcha 위젯을 푸는 것입니다. 이 가이드는 그 단계를 추가합니다. 렌더링된 페이지에서 sitekey를 읽고, API 호출 한 번으로 토큰을 받고, 토큰을 폼에 넣고, 제출합니다.
Scarnox가 오늘 프록시리스 방식으로 푸는 PopularCaptcha 위젯을 다룹니다. 무료 체험 크레딧으로 카드 없이 시작하고, 먼저 테스트 폼에서 스크립트를 시험해 보세요.
Selenium이 해야 할 일
흐름은 네 부분으로 구성됩니다.
- 페이지를 로드하고 위젯이 렌더링될 때까지 기다립니다.
- 위젯에서
data-sitekey속성을 읽습니다. - API에서 토큰을 받아 폼에 넣습니다.
- 토큰이 만료되기 전에 폼을 제출합니다.
captcha에 닿는 것은 세 번째 단계뿐입니다. 나머지는 모두 일반적인 Selenium 작업입니다.
패키지 설치
pip install selenium requests
Selenium 4.6 이상은 맞는 ChromeDriver를 스스로 찾으므로, 드라이버를 직접 내려받을 필요가 없습니다.
전체 스크립트
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
API_KEY = "scarnox_YOURAPIKEY"
API_URL = "https://api.scarnox.com/api/tasks/create"
PAGE_URL = "https://example.com/signup"
def solve(sitekey: str, page_url: str, invisible: bool = False) -> str:
body = {
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
}
if invisible:
body["is_invisible"] = True
r = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json=body,
timeout=185, # 토큰이 준비될 때까지 블로킹합니다
)
data = r.json()
if data.get("errorId") != 0:
raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
return data["solution"]["token"]
INJECT_TOKEN_JS = """
const token = arguments[0];
let field = document.querySelector('[name="h-captcha-response"]');
if (!field) {
field = document.createElement("textarea");
field.name = "h-captcha-response";
field.style.display = "none";
document.querySelector("form").appendChild(field);
}
field.value = token;
let extra = document.querySelector('[name="g-recaptcha-response"]');
if (!extra) {
extra = document.createElement("textarea");
extra.name = "g-recaptcha-response";
extra.style.display = "none";
document.querySelector("form").appendChild(extra);
}
extra.value = token;
"""
def main() -> None:
driver = webdriver.Chrome()
try:
driver.get(PAGE_URL)
widget = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "[data-sitekey]"))
)
sitekey = widget.get_attribute("data-sitekey")
invisible = widget.get_attribute("data-size") == "invisible"
token = solve(sitekey, driver.current_url, invisible=invisible)
# 다른 필드를 먼저 채우고, 토큰은 제출 직전에 넣습니다.
# 토큰은 약 2분 뒤에 만료되기 때문입니다.
driver.find_element(By.NAME, "email").send_keys("you@example.com")
driver.execute_script(INJECT_TOKEN_JS, token)
driver.find_element(By.CSS_SELECTOR, "form button[type=submit]").click()
WebDriverWait(driver, 15).until(EC.url_changes(PAGE_URL))
print("Submitted. Now at:", driver.current_url)
finally:
driver.quit()
if __name__ == "__main__":
main()
프록시리스 PopularCaptcha 풀이에는 프록시가 필요하지 않습니다. 프록시 필드는 빼고, 사이트가 여러분의 평소 연결을 보게 두세요.
작업 순서는 가장 자주 잘못되는 부분입니다. 나머지 폼을 먼저 채우고, 풀고, 토큰을 넣고, 클릭하세요. 다른 필드에 입력하기 전에 풀면, 페이지나 폼이 느릴 때 제출이 토큰의 수명을 넘길 수 있습니다. 풀이와 클릭 사이의 간격은 가능한 한 짧게 유지하고, captcha를 통과했다고 가정하기 전에 결과 페이지에 오류가 없는지 확인하세요.
토큰을 JavaScript로 넣는 이유
대부분의 PopularCaptcha 위젯은 사람이 풀 때 h-captcha-response라는 이름의 숨겨진 textarea에 토큰을 씁니다. Selenium은 사람을 보지 않으므로, 스크립트가 같은 필드를 직접 씁니다. INJECT_TOKEN_JS 스니펫은 두 가지를 합니다.
- 위젯이 이미 만든 textarea가 있으면 재사용합니다.
- 페이지가 만들지 않았다면 textarea를 만들고 폼에 덧붙입니다.
많은 사이트가 호환성을 위해 g-recaptcha-response 이름을 읽으므로, 이 필드도 함께 채웁니다.
보이지 않는 위젯
보이지 않는 위젯에는 체크박스가 없습니다. 배경에서 실행되고, 보통 폼 제출 시 시작됩니다. 스크립트는 data-size="invisible"을 확인하고, 그것을 보면 is_invisible: true를 보냅니다. 일부 사이트는 위젯에 JavaScript 콜백도 붙입니다. 토큰을 넣은 뒤에도 폼이 그대로 있다면 data-callback 속성을 찾아 그 함수에 토큰을 넣어 호출하세요. 이 경우는 보이지 않는 captcha 가이드에서 다룹니다.
테스트에서 사용하기
Selenium은 종단 간(end-to-end) 테스트에도 흔히 쓰는 도구입니다. 직접 운영하는 스테이징 사이트에 captcha가 나타나면, 같은 코드로 테스트가 통과할 수 있습니다. 테스트 환경은 운영 환경과 분리하고, 소유하지 않은 사이트에서는 실행하지 마세요. 테스트 스위트 설정은 자동화 테스트에서의 captcha에 있습니다.
흔한 문제
- 위젯이 전혀 나타나지 않습니다. 대기 시간을 늘리거나, 위젯이 iframe 안에 있는지 확인하세요. 그렇다면
driver.switch_to.frame(...)으로 먼저 프레임으로 전환하세요. - 폼은 제출되는데 사이트가 토큰을 거부합니다. 위젯이 표시된 페이지로 토큰을 보냈는지 확인하세요.
driver.current_url은 쿼리 문자열을 포함해 페이지의 실제 URL과 일치해야 합니다. - 토큰이 만료되었습니다.
solve호출을 제출 단계에 더 가깝게 옮기세요. 토큰은 약 2분 동안 유효합니다. - API에서 타임아웃 오류가 납니다. 스크립트와 같이 약 185초의 타임아웃을 사용하세요. 재시도 로직은 captcha 솔버 오류 처리에서 다룹니다.
요금
성공한 풀이마다 비용을 냅니다. 실패한 풀이는 청구되지 않습니다. 요율은 현재 요금을 확인하고, 무료 체험 크레딧으로 카드 없이 시작하세요.