Solver captcha w Selenium dla Pythona: działający przykład (2026)
Selenium uruchamia prawdziwą przeglądarkę, więc strona się renderuje, a skrypty działają tak, jak dla człowieka. Jedynym krokiem, którego nie potrafi wykonać, jest rozwiązanie widgetu PopularCaptcha. Ten przewodnik dodaje ten krok: odczytaj sitekey z wyrenderowanej strony, pobierz token jednym wywołaniem API, wpisz token do formularza i wyślij go.
Obejmuje widget PopularCaptcha, który Scarnox rozwiązuje dziś w trybie proxyless. Zacznij z darmowym kredytem próbnym, bez karty i przetestuj skrypt najpierw na formularzu testowym.
Co ma zrobić Selenium
Przepływ ma cztery części:
- Załaduj stronę i poczekaj, aż widget się wyrenderuje.
- Odczytaj atrybut
data-sitekeyz widgetu. - Pobierz token z API i wstaw go do formularza.
- Wyślij formularz, zanim token wygaśnie.
Tylko trzeci krok dotyka captcha. Reszta to zwykła praca z Selenium.
Instalacja pakietów
pip install selenium requests
Selenium 4.6 i nowsze samo znajduje pasujący ChromeDriver, więc nie musisz pobierać sterownika ręcznie.
Pełny skrypt
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, # blokuje się, aż token będzie gotowy
)
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)
# Najpierw wypełnij pozostałe pola, potem wstaw token tuż przed wysłaniem,
# bo token wygasa po około dwóch minutach.
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()
Skrypt nie potrzebuje proxy dla rozwiązania PopularCaptcha w trybie proxyless. Pomiń pole proxy i pozwól stronie widzieć twoje zwykłe połączenie.
Kolejność operacji to część, która najczęściej się psuje. Najpierw wypełnij resztę formularza, potem rozwiąż, potem wstaw token, a na końcu kliknij. Jeśli rozwiążesz przed wpisaniem czegokolwiek w pozostałe pola, wolna strona lub wolny formularz może przesunąć wysłanie poza czas życia tokena. Utrzymuj przerwę między rozwiązaniem a kliknięciem jak najkrótszą i sprawdź stronę wyniku pod kątem błędu, zanim uznasz, że captcha przeszła.
Dlaczego token wstawiamy przez JavaScript
Większość widgetów PopularCaptcha, gdy człowiek je rozwiąże, zapisuje token w ukrytym textarea o nazwie h-captcha-response. Ponieważ Selenium nie widzi człowieka, skrypt sam zapisuje to pole. Fragment INJECT_TOKEN_JS robi dwie rzeczy:
- Używa ponownie textarea, jeśli widget już je utworzył.
- Tworzy textarea, jeśli strona tego nie zrobiła, i dołącza je do formularza.
Wypełnia też g-recaptcha-response, bo wiele stron odczytuje tę nazwę ze względu na zgodność.
Widgety niewidoczne
Niewidoczny widget nie ma pola wyboru. Działa w tle i zwykle uruchamia się przy wysyłaniu formularza. Skrypt sprawdza data-size="invisible" i wysyła is_invisible: true, gdy to zobaczy. Niektóre strony dołączają też do widgetu funkcję callback w JavaScripcie. Jeśli formularz zostaje na miejscu po wstawieniu tokena, poszukaj atrybutu data-callback i wywołaj tę funkcję z tokenem. Nasz przewodnik niewidoczna captcha omawia ten przypadek.
Użycie w testach
Selenium to też standardowe narzędzie do testów end-to-end. Jeśli twoja strona stagingowa pokazuje captcha, ten sam kod pozwala testowi ją przejść. Trzymaj środowisko testowe oddzielnie od produkcji i nie uruchamiaj go na stronach, których nie posiadasz. Konfigurację zestawów testowych opisuje captcha w testach automatycznych.
Typowe problemy
- Widget nigdy się nie pojawia. Zwiększ czas oczekiwania albo sprawdź, czy widget znajduje się w iframe. Jeśli tak, przełącz się na ramkę za pomocą
driver.switch_to.frame(...). - Formularz się wysyła, ale strona odrzuca token. Sprawdź, czy token wysłałeś na stronę, na której pokazano widget.
driver.current_urlmusi odpowiadać prawdziwemu adresowi strony, łącznie z parametrami zapytania. - Token wygasł. Przesuń wywołanie
solvebliżej kroku wysyłania. Token żyje około dwóch minut. - Błąd limitu czasu z API. Użyj limitu około 185 sekund, jak w skrypcie. Logikę ponowień opisuje obsługa błędów solvera captcha.
Cennik
Płacisz za każde udane rozwiązanie. Nieudane nie są naliczane. Stawki znajdziesz na stronie cennika, a zacznij z darmowym kredytem próbnym, bez karty.