Эта статья была полезной?
Как обойти капчу Yidun на сайте id7.cloud.huawei.com
Технический специалист
id7.cloud.huawei.com — европейская площадка входа в аккаунт HUAWEI. Страница входа защищена капчей Yidun.
Капча появляется не при каждом входе: показать её или пропустить, решает сервер Huawei. Но параметры для задачи страница готовит заранее, ещё до того как появится окно с картинкой, и их можно прочитать.
По сравнению с обычным Yidun на этом сайте есть три сложности.
Ключа сайта нет в коде страницы. Его отдаёт отдельный запрос, а чтобы собрать этот запрос, сначала нужно получить два других значения от Huawei.
Установлена версия Enterprise. Кроме ключа сайта задаче нужны ещё три значения — challenge, hcg и hct, и все три одноразовые.
Решение не вписывается в форму. Страница упаковывает его в строку JSON вместе с другими значениями и отправляет отдельным параметром запроса.
Параметры задачи
Тип задачи — YidunTaskProxyless, если решать через прокси сервиса, или YidunTask, если подставлять свои.
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
| type | String | Да | YidunTaskProxyless или YidunTask |
| websiteURL | String | Да | Адрес страницы входа: https://id7.cloud.huawei.com/CAS/portal/loginAuth.html |
| websiteKey | String | Да | Ключ сайта, он же captchaId. У этого сайта — 0f743r3g1gm36431pg87n8rz3grz0ym5 |
| userAgent | String | Нет | User-Agent браузера, которым открыта страница |
| yidunGetLib | String | Нет | Адрес файла, который загружает капчу. Для Enterprise рекомендуется передавать |
| yidunApiServerSubdomain | String | Нет | Домен сервера капчи без https://. У Huawei он свой, не стандартный |
| challenge | String | Нет | Одноразовое значение из ответа cscPreprocess |
| hcg | String | Нет | Одноразовое значение из того же ответа |
| hct | Number | Нет | Метка времени из того же ответа |
Три последних параметра документация помечает как необязательные, но для этого сайта они нужны: без них решение относится к обычной версии Yidun, а Huawei ждёт Enterprise.
Для типа YidunTask добавляются данные прокси: proxyType, proxyAddress, proxyPort, proxyLogin и proxyPassword.
Как найти параметры
Постоянные значения у этого сайта такие:
- websiteURL: https://id7.cloud.huawei.com/CAS/portal/loginAuth.html
- websiteKey: 0f743r3g1gm36431pg87n8rz3grz0ym5
- yidunApiServerSubdomain: csc-captcha-dre.security.dbankcloud.com
- yidunGetLib: https://contentcenter-dre.dbankcdn.com/pub_1/cscaptcha_captcha_900_9/b/v3/netease/static/load.min.js
Значения challenge, hcg и hct одноразовые, их нужно получать заново перед каждой задачей. Ниже показано, как их получает сама страница и как повторить это в скрипте.
Шаг первый: запрос cscPreprocess
Откройте страницу входа, нажмите F12 и перейдите на вкладку «Сеть» (Network). Начните вход, и среди запросов появится cscPreprocess с параметром reflushCode. Это запрос методом POST по адресу вида /CAS/IDM_W/ajaxHandler/cscPreprocess?reflushCode=ЧИСЛО.
В его теле страница отправляет captchaType, clientType, lang и sceneId, а также два своих служебных значения — pageToken и pageTokenKey. Оба лежат в объекте localInfo на странице.
Ответ выглядит так:
json
{
"appId": "huaweiup",
"businessId": "huaweiup",
"cdnDomain": "",
"challenge": "f4df3943be517cca2b6060842c4cb96daf6b22e2f15f521ef2177031bab2069b",
"hcg": "1cb7f8d1fa60134e7f5c92b15f96205046cbd91581eb0c16c9d3df63db9967e1",
"hct": 1788597543413,
"isSuccess": 1,
"sceneId": "login",
"serviceDomain": ["csc-adapter-dre.security.dbankcloud.com"],
"type": 2
}
Отсюда берутся challenge, hcg и hct для задачи. Значения businessId, sceneId и serviceDomain понадобятся на следующем шаге, а type — при сборке ответа для сервера.
Про сам запрос есть две детали. Пара pageToken и pageTokenKey срабатывает только один раз: при повторном запросе с той же парой сервер отвечает ошибкой 10000004, и страницу нужно загрузить заново. Параметр captchaType в теле запроса принимает только значение 1; при любом другом приходит ошибка 10000001.
Значение type в ответе — это вид проверки у Yidun. Двойка означает пазл: в библиотеке капчи виды перечислены как JIGSAW 2, POINT 3, SMS 4, INTELLISENSE 5, ICON_POINT 7, INFERENCE 9, WORD_ORDER 10, SPACE 11, VOICE 12. Вид задан настройками Huawei, а не сценарием: запрос со sceneId register вернул то же значение.
Шаг второй: запрос captchaid
Ключа сайта в коде страницы нет. Обёртка Huawei запрашивает его у адреса из serviceDomain:
https://csc-adapter-dre.security.dbankcloud.com/captcha/v4/captchaid?businessId=huaweiup&sceneId=login&lang=ru-RU
Ответ на этот запрос и содержит всё, что осталось:
json
{
"resultCode": 0,
"resultMessage": "Success",
"captchaId": "0f743r3g1gm36431pg87n8rz3grz0ym5",
"vendorServiceDomain": [
"csc-captcha-dre.security.dbankcloud.com",
"csc-captcha-dre.security.dbankcloud.cn"
],
"vendorJsURL": [
"contentcenter-dre.dbankcdn.com/pub_1/cscaptcha_captcha_900_9/b/v3/netease/static/load.min.js"
]
}
Поле captchaId — это websiteKey. Первый адрес из vendorServiceDomain идёт в yidunApiServerSubdomain как есть, без https://. Первый адрес из vendorJsURL идёт в yidunGetLib, но к нему нужно дописать https:// — сервер отдаёт его без схемы.
Значения captchaId, vendorServiceDomain и vendorJsURL при проверке не менялись, поэтому их можно записать в код. А challenge, hcg и hct читайте заново каждый раз.
Примеры кода
Python + requests
Пример получает одноразовые значения, отправляет задачу и забирает решение. Значения pageToken и pageTokenKey возьмите со страницы входа: они разные в каждой сессии.
python
import time
import requests
API_KEY = "ВАШ_API_КЛЮЧ"
PAGE_URL = "https://id7.cloud.huawei.com/CAS/portal/loginAuth.html"
WEBSITE_KEY = "0f743r3g1gm36431pg87n8rz3grz0ym5"
API_SUBDOMAIN = "csc-captcha-dre.security.dbankcloud.com"
GET_LIB = ("https://contentcenter-dre.dbankcdn.com"
"/pub_1/cscaptcha_captcha_900_9/b/v3/netease/static/load.min.js")
PAGE_TOKEN = "ЗНАЧЕНИЕ_СО_СТРАНИЦЫ"
PAGE_TOKEN_KEY = "ЗНАЧЕНИЕ_СО_СТРАНИЦЫ"
session = requests.Session()
session.headers["User-Agent"] = (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
)
preprocess = session.post(
"https://id7.cloud.huawei.com/CAS/IDM_W/ajaxHandler/cscPreprocess",
params={"reflushCode": int(time.time() * 1000)},
data={
"pageToken": PAGE_TOKEN,
"pageTokenKey": PAGE_TOKEN_KEY,
"captchaType": "1",
"clientType": "cas",
"lang": "ru-ru",
"sceneId": "login",
},
timeout=30,
).json()
if preprocess.get("isSuccess") != 1:
raise RuntimeError(f"cscPreprocess не отдал параметры: {preprocess}")
task = {
"type": "YidunTaskProxyless",
"websiteURL": PAGE_URL,
"websiteKey": WEBSITE_KEY,
"userAgent": session.headers["User-Agent"],
"yidunGetLib": GET_LIB,
"yidunApiServerSubdomain": API_SUBDOMAIN,
"challenge": preprocess["challenge"],
"hcg": preprocess["hcg"],
"hct": preprocess["hct"],
}
created = requests.post(
"https://api.rucaptcha.com/createTask",
json={"clientKey": API_KEY, "task": task},
timeout=30,
).json()
if created.get("errorId") != 0:
raise RuntimeError(f"Задача не создана: {created}")
task_id = created["taskId"]
print("Задача создана, id", task_id)
for _ in range(24):
time.sleep(5)
result = requests.post(
"https://api.rucaptcha.com/getTaskResult",
json={"clientKey": API_KEY, "taskId": task_id},
timeout=30,
).json()
if result.get("errorId") != 0:
raise RuntimeError(f"Ошибка: {result}")
if result.get("status") == "ready":
validate = result["solution"]["token"]
print("Решение получено:", validate[:30], "…")
break
else:
raise RuntimeError("Решение не пришло за отведённое время")
Python + Playwright
Пример открывает страницу входа, читает с неё служебные значения, повторяет оба запроса Huawei, отправляет задачу и собирает готовый authcode.
python
import json
import os
import time
import requests
from playwright.sync_api import sync_playwright
API_KEY = os.getenv("APIKEY_RUCAPTCHA", "ВАШ_API_КЛЮЧ")
PAGE_URL = "https://id7.cloud.huawei.com/CAS/portal/loginAuth.html"
WEBSITE_KEY = "0f743r3g1gm36431pg87n8rz3grz0ym5"
API_SUBDOMAIN = "csc-captcha-dre.security.dbankcloud.com"
GET_LIB = ("https://contentcenter-dre.dbankcdn.com"
"/pub_1/cscaptcha_captcha_900_9/b/v3/netease/static/load.min.js")
def solve(task):
created = requests.post(
"https://api.rucaptcha.com/createTask",
json={"clientKey": API_KEY, "task": task},
timeout=30,
).json()
if created.get("errorId") != 0:
raise RuntimeError(f"Задача не создана: {created}")
task_id = created["taskId"]
print("Задача создана, id", task_id)
for _ in range(24):
time.sleep(5)
result = requests.post(
"https://api.rucaptcha.com/getTaskResult",
json={"clientKey": API_KEY, "taskId": task_id},
timeout=30,
).json()
if result.get("errorId") != 0:
raise RuntimeError(f"Ошибка: {result}")
if result.get("status") == "ready":
return result["solution"]["token"]
raise RuntimeError("Решение не пришло за отведённое время")
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto(PAGE_URL)
page.wait_for_function("window.localInfo !== undefined", timeout=30000)
local_info = page.evaluate("""() => ({
pageToken: window.localInfo.pageToken,
pageTokenKey: window.localInfo.pageTokenKey,
sceneId: window.localInfo.cscSceneId,
captchaType: window.localInfo.displayCaptchaType,
lang: window.localInfo.lang || 'ru-ru',
})""")
preprocess = page.evaluate("""async (info) => {
const body = new URLSearchParams({
pageToken: info.pageToken,
pageTokenKey: info.pageTokenKey,
captchaType: info.captchaType,
clientType: 'cas',
lang: info.lang,
sceneId: info.sceneId,
});
const url = '/CAS/IDM_W/ajaxHandler/cscPreprocess?reflushCode=' + Date.now();
const response = await fetch(url, {
method: 'POST',
credentials: 'include',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body,
});
return response.json();
}""", local_info)
if preprocess.get("isSuccess") != 1:
raise RuntimeError(f"cscPreprocess не отдал параметры: {preprocess}")
user_agent = page.evaluate("navigator.userAgent")
validate = solve({
"type": "YidunTaskProxyless",
"websiteURL": PAGE_URL,
"websiteKey": WEBSITE_KEY,
"userAgent": user_agent,
"yidunGetLib": GET_LIB,
"yidunApiServerSubdomain": API_SUBDOMAIN,
"challenge": preprocess["challenge"],
"hcg": preprocess["hcg"],
"hct": preprocess["hct"],
})
authcode = json.dumps({
"type": preprocess["type"],
"sceneId": preprocess["sceneId"],
"lang": local_info["lang"],
"challenge": preprocess["challenge"],
"hcg": preprocess["hcg"],
"hct": preprocess["hct"],
"validate": validate,
})
print("Готовый authcode:", authcode[:80], "…")
except Exception as e:
print(f"Ошибка: {e}")
finally:
browser.close()
Как использовать полученный токен
Сервис возвращает решение в поле solution.token. У Yidun это значение называется validate. Обычно его кладут в скрытое поле формы. На странице входа Huawei такое поле есть — это input с идентификатором captchaInfo внутри блока hwid-captchaHtml, — но обработчик страницы его не читает.
Вместо этого страница собирает из решения строку JSON и отправляет её отдельным параметром запроса под именем authcode. В коде страницы это выглядит так:
javascript
getRandomCode: function (result) {
var t = { validate: result.validate };
return JSON.stringify(be.extend(this.secondverifyParam, t));
}
Объект secondverifyParam страница собрала раньше, из ответа cscPreprocess. В итоге в authcode попадает семь значений:
json
{
"type": 2,
"sceneId": "login",
"lang": "ru-RU",
"challenge": "f4df3943be517cca2b6060842c4cb96daf6b22e2f15f521ef2177031bab2069b",
"hcg": "1cb7f8d1fa60134e7f5c92b15f96205046cbd91581eb0c16c9d3df63db9967e1",
"hct": 1788597543413,
"validate": "РЕШЕНИЕ_ОТ_СЕРВИСА"
}
Отсюда два правила. Значения challenge, hcg и hct нужны дважды: сначала в задаче, потом в authcode, и это должны быть одни и те же значения. И решение само по себе бесполезно: сервер ждёт его внутри строки, а не отдельно.
Частые ошибки и решения
| Ошибка или проблема | Причина | Решение |
|---|---|---|
| Сервис решает капчу, но сервер Huawei отклоняет ответ | В задаче не были переданы challenge, hcg и hct | Передавайте все три: на этом сайте стоит версия Enterprise |
| Ошибка при создании задачи из-за ключа сайта | Ключ искали в коде страницы, а его там нет | Ключ отдаёт запрос captcha/v4/captchaid, он же указан в статье |
| Ответ приходит, но сервер отвечает ошибкой проверки | В задаче и в authcode оказались разные challenge, hcg и hct | Получите тройку один раз и используйте её в обоих местах |
| Запрос cscPreprocess отвечает ошибкой 10000004 | Пара pageToken и pageTokenKey уже была использована | Значения одноразовые. Загрузите страницу заново и возьмите новые |
| Запрос cscPreprocess отвечает ошибкой 10000001 | В теле запроса передан captchaType, отличный от 1 | Здесь допустимо только значение 1. С видом проверки у Yidun это поле не связано |
| Форма уходит без решения | Решение записали в скрытое поле captchaInfo | Поле на странице есть, но обработчик его не читает. Собирайте authcode |
| Капча не появляется совсем | Сервер решил, что проверка не нужна | Это нормально. Обрабатывайте оба случая: с капчей и без неё |
| Сервер отвечает, что параметры устарели | Между получением тройки и отправкой прошло слишком много времени | Собирайте параметры прямо перед созданием задачи |
Полный список кодов ошибок находится на странице «Коды ошибок», ссылка на неё ниже.
Полезные ссылки
- Документация API по Yidun: https://rucaptcha.com/api-docs/yidun-necaptcha
- Как обойти капчу Yidun: https://rucaptcha.com/h/how-to-bypass-yidun-captcha
- Песочница для тестирования API: https://rucaptcha.com/api-docs/debugging
- Работа с прокси: https://rucaptcha.com/api-docs/proxy
- Коды ошибок: https://rucaptcha.com/api-docs/error-codes
- Python SDK на GitHub: https://github.com/2captcha/2captcha-python