Связка работает по простому правилу: трафик страницы идёт через резидентный шлюз Smartproxy, а задача CAPTCHA уходит в API CaptchaAI напрямую. Прокси отвечает за то, с какого IP сайт видит ваш запрос, CaptchaAI — за токен, который вы кладёте в форму. Большая часть проблем в такой интеграции возникает именно тогда, когда эти две роли путают.
Ниже — рабочая схема: какой пул брать, как удержать один IP на весь цикл «загрузка — решение — отправка», как это выглядит в Python, Selenium и Node.js и что делать с типовыми сбоями.
Какой шлюз Smartproxy выбрать под задачу
Пулы Smartproxy по-разному ведут себя на страницах с проверками. Ориентир по документации провайдера:
| Тип | Размер пула | Под какие задачи | Как часто всплывает CAPTCHA |
|---|---|---|---|
| Резидентный | 55 млн+ IP | Общий парсинг | Низко |
| Датацентровый | 100 тыс.+ IP | Быстрая выкачка данных | Средне-высоко |
| Мобильный | 10 млн+ IP | Мобильные версии сайтов | Очень низко |
| ISP (статический резидентный) | Статические IP резидентного уровня | Долгие сессии | Низко |
Вывод один: если проверки появляются на каждом запросе, вы почти наверняка сидите на датацентровом шлюзе. Резидентный или ISP-пул снижает их частоту, но не убирает — решатель в пайплайне нужен в любом случае.
Шаг 1: базовая связка на Python
Учётные данные шлюза и API-ключ держите в переменных окружения — в примере они вынесены в константы только для читаемости. Задача уходит в in.php, результат забирается опросом res.php.
import requests
import time
SMARTPROXY_USER = "spuser"
SMARTPROXY_PASS = "sppassword"
SMARTPROXY_HOST = "gate.smartproxy.com"
SMARTPROXY_PORT = 10001
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
proxies = {
"http": f"http://{SMARTPROXY_USER}:{SMARTPROXY_PASS}@{SMARTPROXY_HOST}:{SMARTPROXY_PORT}",
"https": f"http://{SMARTPROXY_USER}:{SMARTPROXY_PASS}@{SMARTPROXY_HOST}:{SMARTPROXY_PORT}",
}
def fetch_page(url):
return requests.get(url, proxies=proxies, timeout=30)
def solve_captcha(site_url, sitekey, captcha_type="recaptcha_v2"):
submit_data = {
"key": CAPTCHAAI_KEY,
"pageurl": site_url,
"json": 1,
}
if captcha_type == "turnstile":
submit_data["method"] = "turnstile"
submit_data["sitekey"] = sitekey
else:
submit_data["method"] = "userrecaptcha"
submit_data["googlekey"] = sitekey
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=submit_data)
data = resp.json()
if data["status"] != 1:
raise Exception(f"Submit failed: {data['request']}")
task_id = data["request"]
for _ in range(60):
time.sleep(5)
resp = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY,
"action": "get",
"id": task_id,
"json": 1,
})
data = resp.json()
if data["request"] == "CAPCHA_NOT_READY":
continue
if data["status"] == 1:
return data["request"]
raise Exception(f"Solve: {data['request']}")
raise TimeoutError("Timeout")
Обратите внимание: запрос к CaptchaAI идёт без прокси. Решателю нужны только pageurl и sitekey; прокси остаётся на слое fetch_page. Если разнести эти два слоя сразу, дальнейшая отладка становится вдвое короче.
Шаг 2: sticky-сессии — почему без них токен отклоняют
Это главная причина, по которой «всё работает, но форма не проходит». Ротируемый шлюз меняет IP между запросами: страницу вы загрузили с одного адреса, а форму отправили уже с другого. Сайт видит несовпадение и отбрасывает токен, хотя решение было корректным. Лечится закреплением IP на весь цикл — в имя пользователя добавляется идентификатор сессии и её длительность.
import random
import string
def get_sticky_proxy(session_duration_minutes=10):
"""Create a sticky session proxy (same IP for duration)."""
session_id = "".join(random.choices(string.ascii_lowercase + string.digits, k=8))
proxy_url = (
f"http://{SMARTPROXY_USER}"
f"-session-{session_id}"
f"-sessionduration-{session_duration_minutes}"
f":{SMARTPROXY_PASS}@{SMARTPROXY_HOST}:{SMARTPROXY_PORT}"
)
return {"http": proxy_url, "https": proxy_url}
# Use same IP for entire CAPTCHA workflow
sticky = get_sticky_proxy(session_duration_minutes=10)
# Page load
resp = requests.get("https://staging.example.com/qa-form", proxies=sticky)
# Solve CAPTCHA
token = solve_captcha("https://staging.example.com/qa-form", "SITEKEY_HERE")
# Submit with same IP
resp = requests.post(
"https://target.com/submit",
data={"g-recaptcha-response": token},
proxies=sticky,
)
Десяти минут хватает на типовой сценарий: открыли страницу, дождались решения, отправили форму. Для многошаговых форм — регистрация в несколько экранов, длинные заявки, анкеты — ставьте 30 минут.
Шаг 3: выбор страны выхода
Гео-таргетинг тоже задаётся через имя пользователя, отдельный endpoint для этого не нужен.
# Smartproxy country targeting via username
def get_country_proxy(country_code):
proxy_url = (
f"http://{SMARTPROXY_USER}"
f"-country-{country_code}"
f":{SMARTPROXY_PASS}@{SMARTPROXY_HOST}:{SMARTPROXY_PORT}"
)
return {"http": proxy_url, "https": proxy_url}
# US proxy
us_proxy = get_country_proxy("us")
# UK proxy
uk_proxy = get_country_proxy("gb")
# Germany proxy
de_proxy = get_country_proxy("de")
Типичный локальный случай: команда в Алматы или Минске тестирует форму регистрации европейского сервиса. Из локального датацентрового адреса страница встретит вас проверкой, а иногда и языковой версией не того рынка. Резидентный выход в нужной стране плюс sticky-сессия дают воспроизводимый прогон QA, а не «как повезло с IP».
И оговорка про данные: собирайте только то, что вы вправе обрабатывать — 152-ФЗ «О персональных данных» для российских пользователей, привычная GDPR-дисциплина для трансграничных проектов.
Шаг 4: Selenium с прокси и подстановкой токена
Схема та же, но авторизация через --proxy-server в Chrome не передаётся: логин и пароль придётся отдавать через Selenium Wire или расширение. Идентификатор сессии обязателен и здесь.
from selenium import webdriver
from selenium.webdriver.common.by import By
def create_smartproxy_driver(country=None, sticky_session=None):
proxy_user = SMARTPROXY_USER
if country:
proxy_user += f"-country-{country}"
if sticky_session:
proxy_user += f"-session-{sticky_session}"
proxy_url = f"{proxy_user}:{SMARTPROXY_PASS}@{SMARTPROXY_HOST}:{SMARTPROXY_PORT}"
options = webdriver.ChromeOptions()
options.add_argument(f"--proxy-server=http://{SMARTPROXY_HOST}:{SMARTPROXY_PORT}")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--window-size=1920,1080")
# For authenticated proxies, use seleniumwire or extension
return webdriver.Chrome(options=options)
def scrape_with_captcha(url, country="us"):
session_id = "".join(random.choices(string.ascii_lowercase, k=8))
driver = create_smartproxy_driver(country=country, sticky_session=session_id)
try:
driver.get(url)
time.sleep(3)
sitekey = driver.execute_script(
"return document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey')"
)
if sitekey:
token = solve_captcha(url, sitekey)
driver.execute_script(f"""
document.querySelector('#g-recaptcha-response').value = '{token}';
""")
driver.find_element(By.CSS_SELECTOR, "form").submit()
time.sleep(3)
return driver.page_source
finally:
driver.quit()
Подстановка токена в #g-recaptcha-response — стандартный приём для reCAPTCHA v2. У Cloudflare Turnstile поле ответа называется иначе, поэтому при переключении типа проверки не забудьте поменять и селектор, и метод отправки задачи.
Шаг 5: то же самое на Node.js
Логика не меняется: агент прокси навешивается на запрос к целевой странице, вызов CaptchaAI идёт напрямую.
const axios = require("axios");
const HttpsProxyAgent = require("https-proxy-agent");
const CAPTCHAAI_KEY = "YOUR_API_KEY";
function getSmartproxyAgent(options = {}) {
let user = "spuser";
if (options.country) user += `-country-${options.country}`;
if (options.session) user += `-session-${options.session}`;
return new HttpsProxyAgent(
`http://${user}:[email protected]:10001`
);
}
async function scrapeWithCaptcha(url, sitekey) {
const agent = getSmartproxyAgent({
country: "us",
session: `sess-${Date.now()}`,
});
// Fetch page through proxy
const pageResp = await axios.get(url, { httpsAgent: agent });
// Solve CAPTCHA via CaptchaAI (no proxy needed)
const submitResp = await axios.post(
"https://ocr.captchaai.com/in.php",
null,
{
params: {
key: CAPTCHAAI_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: url,
json: 1,
},
}
);
const taskId = submitResp.data.request;
// Poll for result
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: {
key: CAPTCHAAI_KEY,
action: "get",
id: taskId,
json: 1,
},
});
if (result.data.request === "CAPCHA_NOT_READY") continue;
if (result.data.status === 1) return result.data.request;
}
throw new Error("Timeout");
}
Шаг 6: параллельная обработка и потоки
На очереди из сотен страниц вы упираетесь в два лимита: параллельные соединения шлюза Smartproxy и число потоков в тарифе CaptchaAI. Тарификация идёт по количеству одновременных задач, а не решений, и в пределах месяца решения по потоку не ограничены.
Ориентир простой: max_workers не должен превышать число потоков тарифа, иначе часть задач встанет в очередь. BASIC ($15/мес, 5 потоков) закрывает отладку, STANDARD ($30/мес, 15 потоков) — регулярный QA-пайплайн, ADVANCE ($90/мес, 50 потоков) — параллельный парсинг. Выше идут PREMIUM ($170/мес, 100 потоков), CORPORATE ($240/мес, 150 потоков), ENTERPRISE ($300/мес, 200 потоков) и линейка VIP-1 ($1,500/мес, 1000 потоков), VIP-2 ($4,500/мес, 3000 потоков), VIP-3 ($7,500/мес, 5000 потоков). Цены в USD.
Для агентств и фрилансеров, выставляющих счета в волатильной локальной валюте, это удобно тем, что стоимость прогона не зависит от того, сколько страниц оказались с проверкой.
from concurrent.futures import ThreadPoolExecutor, as_completed
def process_url(url):
session_id = "".join(random.choices(string.ascii_lowercase, k=8))
proxy = get_sticky_proxy(10)
try:
resp = requests.get(url, proxies=proxy, timeout=30)
# Check if CAPTCHA is present (simplified detection)
if "data-sitekey" in resp.text:
import re
match = re.search(r'data-sitekey="([^"]+)"', resp.text)
if match:
sitekey = match.group(1)
token = solve_captcha(url, sitekey)
return {"url": url, "status": "solved", "token": token[:30]}
return {"url": url, "status": "no_captcha"}
except Exception as e:
return {"url": url, "status": "error", "error": str(e)}
urls = [
"https://site1.com/page",
"https://site2.com/page",
"https://site3.com/page",
]
with ThreadPoolExecutor(max_workers=5) as executor:
futures = {executor.submit(process_url, u): u for u in urls}
for future in as_completed(futures):
result = future.result()
print(f"[{result['status']}] {result['url']}")
Разбор типовых сбоев
| Симптом | Причина | Что сделать |
|---|---|---|
407 Proxy Authentication Required |
Неверный формат логина или пароля шлюза | Сверьте учётные данные в панели управления Smartproxy; проверьте, не потерялись ли суффиксы -country- и -session- |
| IP меняется посреди сценария | Sticky-сессия не задана | Добавьте -session-ID и -sessionduration- в имя пользователя |
| Проверка появляется на каждом запросе | Работа идёт через датацентровый шлюз | Переключитесь на резидентный или ISP-пул |
| Долгие ответы | Перегруженная гео-цель | Возьмите другую страну или город выхода |
| Токен отклонён после успешного решения | IP сменился между загрузкой страницы и отправкой формы | Увеличьте длительность sticky-сессии |
CAPCHA_NOT_READY не сменяется результатом |
Неверная конфигурация задачи или слишком ранний опрос | Проверьте sitekey и pageurl; интервал опроса 5 с уже заложен в примере |
Отладку начинайте с разделения слоёв: сначала убедитесь, что страница открывается через прокси (fetch_page без решателя), и только потом подключайте CaptchaAI.
Часто задаваемые вопросы
Нужно ли отправлять запросы к CaptchaAI через Smartproxy?
Нет. Вызовы in.php и res.php идут напрямую с вашего сервера: прокси нужен целевому сайту, а не решателю, и лишний хоп только добавит задержку.
Можно ли передать IP Smartproxy в саму задачу CaptchaAI?
Да — в запросе на отправку поддерживается параметр proxy. Это имеет смысл, когда сайт жёстко привязывает выданную проверку к адресу, с которого её запросили.
Какие типы CAPTCHA закрывает эта схема?
reCAPTCHA v2 (включая invisible и Enterprise), reCAPTCHA v3, Cloudflare Turnstile и Challenge, GeeTest v3, изображения, текстовые и grid-задачи, BLS CAPTCHA. CaptchaFox (beta), Friendly Captcha (beta) и Lemin (beta) — в бете. hCaptcha и FunCaptcha не поддерживаются, GeeTest v4 заявлен как скорый, но пока недоступен. Меняется только параметр method в запросе — прокси-обвязка остаётся той же.
Сколько потоков брать под очередь из 1000 страниц?
Считайте от параллелизма, а не от объёма: если вы обрабатываете 15 страниц одновременно и проверка встречается примерно на трети, 15 потоков дают запас. Решения в пределах потока отдельно не тарифицируются, так что более высокий тариф берут ради скорости.
Правда ли, что мобильный пул реже упирается в проверки?
На части сайтов — да, по данным провайдера. Но трафик там дороже, а пул меньше, поэтому мобильный выход разумно держать для проблемных доменов, а основную массу гонять через резидентный.
Связанные материалы
- Резидентные прокси Bright Data вместе с CaptchaAI
- Ротация резидентных прокси при решении CAPTCHA
- Почему автоматизация браузера падает, а вызов API проходит
Соберите пайплайн один раз: резидентный выход Smartproxy, sticky-сессия и решатель. Получите API-ключ CaptchaAI и начните с первой формы в staging.