Эта статья была полезной?
Как обойти капчу на сайте SHEIN
Технический специалист
Сайт SHEIN (shein.com) использует собственную систему защиты от ботов, которая не опирается на сторонние решения вроде reCAPTCHA или hCaptcha. При подозрительной активности посетитель перенаправляется на внутренний шлюз проверки по адресу /risk/challenge.
Главная особенность этой капчи заключается в том, что здесь нет sitekey или токена, который можно просто подставить в форму. Головоломка решается непосредственно на странице с помощью кликов мышью, что требует использования настоящего браузера (например, Playwright, Puppeteer или Selenium). В этом руководстве мы разберем, как определить тип головоломки, сделать правильные скриншоты, отправить их в API и программно прокликать ответ.
Параметры задачи (API v2)
В зависимости от типа головоломки, отображаемой на странице, используются разные типы задач при отправке через эндпоинт createTask.
Для последовательности иконок (CoordinatesTask)
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
| clientKey | String | Да | Ваш API-ключ |
| type | String | Да | CoordinatesTask |
| body | String | Да | Скриншот основного изображения в формате Base64 (без префикса data:image/png;base64,) |
| imgInstructions | String | Да | Скриншот полоски с иконками-подсказками в формате Base64 |
| comment | String | Да | Текстовая инструкция для работника, например: Click the icons shown in the instruction, in the same order, left to right |
Для сетки 3x3 (GridTask)
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
| clientKey | String | Да | Ваш API-ключ |
| type | String | Да | GridTask |
| body | String | Да | Скриншот всей сетки 3x3 в формате Base64 |
| rows | Integer | Да | Количество строк (всегда 3) |
| columns | Integer | Да | Количество столбцов (всегда 3) |
| imgInstructions | String | Да | Скриншот иконки-образца в формате Base64 |
| comment | String | Да | Текстовая инструкция, например: Select exactly 3 images that show the same action or object as the small icon |
Как определить тип капчи на странице
Поскольку sitekey отсутствует, ваша задача — определить, на каком этапе проверки находится пользователь.
- Откройте инструменты разработчика (F12) и перейдите на вкладку Сеть (Network).
- Если в URL страницы присутствует /risk/challenge, вы находитесь на шлюзе проверки.
- Перейдите на вкладку Элементы (Elements) и проанализируйте DOM:
- Чекбокс: ищите элемент с текстом I am human.
- Последовательность иконок: ищите контейнер .captcha_click_wrapper с элементами .pic_wrapper (основная картинка) и .pic_elg_wrapper (полоска иконок).
- Сетка 3x3: ищите веб-компонент
Примеры кода
Python + requests (API v2)
Пример отправки задачи CoordinatesTask или GridTask и получения результата.
python
import requests
import time
import base64
import os
API_KEY = os.environ.get("APIKEY", "ВАШ_API_КЛЮЧ")
def solve_captcha_task(task_payload: dict, timeout: int = 180) -> dict:
url = "https://2captcha.com/createTask"
headers = {"Content-Type": "application/json"}
payload = {"clientKey": API_KEY, "task": task_payload}
response = requests.post(url, headers=headers, json=payload).json()
if response.get("errorId") != 0:
raise RuntimeError(f"Ошибка создания задачи: {response.get('errorDescription')}")
task_id = response["taskId"]
print(f"Задача создана, ID: {task_id}")
res_url = "https://2captcha.com/getTaskResult"
deadline = time.time() + timeout
while time.time() < deadline:
time.sleep(5)
res_payload = {"clientKey": API_KEY, "taskId": task_id}
res_response = requests.post(res_url, headers=headers, json=res_payload).json()
if res_response.get("errorId") != 0:
raise RuntimeError(f"Ошибка получения результата: {res_response.get('errorDescription')}")
if res_response.get("status") == "ready":
return res_response["solution"]
raise TimeoutError("Превышено время ожидания решения капчи")
# Пример использования для CoordinatesTask:
# task = {
# "type": "CoordinatesTask",
# "body": "iVBORw0KGgoAAAANSUhEUg...", # Base64 основного изображения
# "imgInstructions": "iVBORw0KGgoAAAANSUhEUg...", # Base64 полоски иконок
# "comment": "Click the icons shown in the instruction, in the same order, left to right"
# }
# solution = solve_captcha_task(task)
# print(solution) # Вернет {"coordinates": [{"x": 118, "y": 402}, ...]}
Python + Playwright (Полный цикл решения)
Пример автоматизации, который определяет тип капчи, делает скриншоты, отправляет задачу в API и прокликивает результат.
python
import os
import time
import requests
from playwright.sync_api import sync_playwright
API_KEY = os.environ.get("APIKEY", "ВАШ_API_КЛЮЧ")
TARGET_URL = "https://us.shein.com/pdsearch/dress/"
# JavaScript для определения текущего шага капчи и получения координат элементов
STATE_JS = """
() => {
const roots = [];
const collect = (root) => {
roots.push(root);
for (const el of root.querySelectorAll('*')) if (el.shadowRoot) collect(el.shadowRoot);
};
collect(document);
const visible = (e) => {
if (!e) return false;
const r = e.getBoundingClientRect(), s = getComputedStyle(e);
return r.width > 0 && r.height > 0 && s.display !== 'none' && s.visibility !== 'hidden';
};
const qa = (sel) => roots.flatMap((r) => [...r.querySelectorAll(sel)]);
const rect = (e) => { const r = e.getBoundingClientRect(); return [r.x, r.y, r.width, r.height]; };
const first = (sel) => { const e = qa(sel).find(visible); return e ? rect(e) : null; };
const pic = qa('.captcha_click_wrapper .pic_wrapper').find(visible);
if (pic) {
return {
stage: 'icon_click',
image: rect(pic),
icons: first('.captcha_click_wrapper .pic_elg_wrapper'),
confirm: first('.captcha_click_confirm'),
refresh: first('.captcha_click_refresh')
};
}
const tiles = qa('.nine-content-img').filter(visible);
if (tiles.length) {
return {
stage: 'nine_captcha',
tiles: tiles.map(rect),
icon: first('.header-content-img'),
refresh: first('.nine-refresh')
};
}
for (const r of roots) {
for (const e of r.querySelectorAll('*')) {
if (e.childElementCount === 0 && e.textContent.trim() === 'I am human' && visible(e)) {
return {stage: 'one_pass', checkbox: rect(e)};
}
}
}
return {stage: 'none'};
}
"""
def send_task(task_data):
url = "https://2captcha.com/createTask"
res = requests.post(url, json={"clientKey": API_KEY, "task": task_data}).json()
if res.get("errorId") != 0:
raise Exception(f"Task error: {res.get('errorDescription')}")
task_id = res["taskId"]
for _ in range(30):
time.sleep(5)
r = requests.post("https://2captcha.com/getTaskResult", json={"clientKey": API_KEY, "taskId": task_id}).json()
if r.get("status") == "ready":
return r["solution"]
raise TimeoutError("Captcha solving timeout")
def solve_shein_challenge(page, max_rounds=5):
if "/risk/challenge" not in page.url:
return True
page.wait_for_function(f"({STATE_JS})().stage !== 'none'", timeout=15000)
for round_num in range(1, max_rounds + 1):
time.sleep(1.5) # Даем время на загрузку новых картинок
state = page.evaluate(STATE_JS)
if state["stage"] == "one_pass":
label = state["checkbox"]
page.mouse.click(label[0] - 20, label[1] + label[3] / 2)
time.sleep(3)
if "/risk/challenge" not in page.url:
return True
elif state["stage"] == "icon_click":
image_png = page.screenshot(clip={"x": state["image"][0], "y": state["image"][1], "width": state["image"][2], "height": state["image"][3]})
icons_png = page.screenshot(clip={"x": state["icons"][0], "y": state["icons"][1], "width": state["icons"][2], "height": state["icons"][3]})
import base64
solution = send_task({
"type": "CoordinatesTask",
"body": base64.b64encode(image_png).decode(),
"imgInstructions": base64.b64encode(icons_png).decode(),
"comment": "Click the icons shown in the instruction, in the same order, left to right"
})
points = solution.get("coordinates", [])
if len(points) < 2:
page.mouse.click(state["refresh"][0] + state["refresh"][2]/2, state["refresh"][1] + state["refresh"][3]/2)
continue
# Пересчет координат с учетом device pixel ratio
w, h = len(image_png), len(icons_png) # Упрощенно, в реальности нужно парсить заголовки PNG
# Для точности лучше использовать библиотеку для чтения размеров PNG, но здесь показан принцип
x0, y0 = state["image"][0], state["image"][1]
for p in points:
page.mouse.click(x0 + p["x"], y0 + p["y"])
time.sleep(0.4)
page.mouse.click(state["confirm"][0] + state["confirm"][2]/2, state["confirm"][1] + state["confirm"][3]/2)
elif state["stage"] == "nine_captcha":
tiles = sorted(state["tiles"], key=lambda t: (round(t[1] / t[3]), t[0]))
x0, y0 = min(t[0] for t in tiles), min(t[1] for t in tiles)
x1, y1 = max(t[0] + t[2] for t in tiles), max(t[1] + t[3] for t in tiles)
grid_png = page.screenshot(clip={"x": x0, "y": y0, "width": x1 - x0, "height": y1 - y0})
icon_png = page.screenshot(clip={"x": state["icon"][0], "y": state["icon"][1], "width": state["icon"][2], "height": state["icon"][3]})
import base64
solution = send_task({
"type": "GridTask",
"body": base64.b64encode(grid_png).decode(),
"rows": 3, "columns": 3,
"imgInstructions": base64.b64encode(icon_png).decode(),
"comment": "Select exactly 3 images that show the same action or object as the small icon"
})
picks = [n for n in solution.get("click", []) if 1 <= n <= 9]
if len(picks) != 3:
page.mouse.click(state["refresh"][0] + state["refresh"][2]/2, state["refresh"][1] + state["refresh"][3]/2)
continue
for n in picks:
t = tiles[n - 1]
page.mouse.click(t[0] + t[2]/2, t[1] + t[3]/2)
time.sleep(0.4)
try:
page.wait_for_url(lambda url: "/risk/challenge" not in url, timeout=8000)
print(f"Капча успешно пройдена в раунде {round_num}")
return True
except Exception:
print(f"Раунд {round_num} не принят, пробуем новую головоломку")
return False
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto(TARGET_URL)
if solve_shein_challenge(page):
page.wait_for_load_state("domcontentloaded")
print("Успешный вход:", page.title())
browser.close()
Как использовать полученный результат
Поскольку SHEIN не использует токены, результат решения используется для прямого взаимодействия со страницей:
- Для последовательности иконок (CoordinatesTask): API возвращает массив координат [{"x": 118, "y": 402}, ...]. Кликайте строго в этом порядке. Важно: координаты даны в пикселях отправленного изображения. Если вы делаете скриншот на HiDPI-экране, разделите x и y на devicePixelRatio перед добавлением смещения элемента на странице. После всех кликов нажмите кнопку Confirm.
- Для сетки 3x3 (GridTask): API возвращает номера плиток от 1 до 9 (например, [2, 5, 9]). Плитки нумеруются слева направо, сверху вниз. Кликайте по центрам соответствующих плиток. Кнопки Confirm здесь нет, виджет отправляет ответ автоматически после третьего клика.
- Если SHEIN отклоняет ответ (возвращает code=9001 System error), не отправляйте жалобу на неправильное решение сразу. Это особенность риск-оценки SHEIN, а не ошибка работника. Просто обновите головоломку и попробуйте снова. Закладывайте 2-3 раунда в своем скрипте.
Альтернативные способы решения
Помимо прямого API, существуют два дополнительных способа обхода капчи на SHEIN, которые могут быть полезны в различных сценариях автоматизации.
1. Расширение для браузера (Captcha Bypass Extension)
Если вы работаете вручную или используете автоматизацию на базе Selenium/Playwright с реальным браузером, вы можете установить наше специальное расширение для обхода капч.
Преимущества:
- Не требует написания сложного кода для снятия скриншотов и отправки запросов
- Автоматически определяет появление головоломки и решает её в фоновом режиме
- Работает с большинством популярных типов капч, включая кастомные задачи SHEIN
- Идеально подходит для ручного серфинга или сложных сценариев автоматизации
Подробнее о расширении: https://2captcha.com/captcha-bypass-extension
2. Browser API (Scraper)
Для сложных задач парсинга, где нужно не только обойти капчу, но и извлечь данные о товарах после успешного прохождения проверки, мы предлагаем Browser API — облачное решение на базе headless-браузеров.
Преимущества:
- Полностью управляемый облачный браузер с встроенной поддержкой обхода капч
- Не нужно настраивать прокси, User-Agent или бороться с блокировками
- Встроенные функции для извлечения данных (скриншоты, HTML, выполнение JavaScript)
- Автоматическое решение капч при навигации по сайту
- Идеально для массового парсинга и сбора данных
Подробнее о Browser API: https://2captcha.com/scraper/browser-api/dashboard
Частые ошибки и решения
| Ошибка / Проблема | Причина | Решение |
|---|---|---|
| Клики попадают мимо картинки | Координаты не пересчитаны из пикселей скриншота в CSS-пиксели | Разделите координаты на отношение размера скриншота к размеру элемента (учитывайте devicePixelRatio). |
| Плитки сетки не находятся | Они находятся внутри Shadow DOM элемента | Используйте рекурсивный обход всех shadowRoot, как показано в примере STATE_JS. |
| Работник получает пустую картинку | Скриншот сделан до загрузки нового спрайта после обновления | Подождите 1-2 секунды после нажатия кнопки обновления, прежде чем снимать скриншоты. |
| Правильный ответ отклонен (code=9001) | Риск-оценка SHEIN, а не ошибка в ответе работника | Повторите со следующей головоломкой. Закладывайте 2-3 раунда в логику скрипта. |
| Отклоняются все ответы | SHEIN пометил сам профиль браузера или IP как подозрительный | Смените профиль браузера и используйте резидентские прокси. Дополнительные раунды не помогут. |
| ERROR_ZERO_BALANCE или ERROR_KEY_DOES_NOT_EXIST | Проблема с аккаунтом или ключом | Прекратите повторы, пополните баланс или проверьте корректность API-ключа. |
Полезные ссылки
- Песочница для тестирования API: https://2captcha.com/setting#sandbox
- Документация API по CoordinatesTask: https://2captcha.com/api-docs/coordinates
- Документация API по GridTask: https://2captcha.com/api-docs/grid
- Расширение для обхода капч: https://2captcha.com/captcha-bypass-extension
- Browser API для парсинга: https://2captcha.com/scraper/browser-api/dashboard
- Python SDK на GitHub: https://github.com/2captcha/2captcha-python
- Другие примеры обхода капч на сайтах: https://2captcha.com/h?category=sites