في صفحة تعمل بـ reCAPTCHA v3 لا يوجد ما تنظر إليه لتعرف إصدارها: لا مربع تأشير ولا صورة، بل سطر <script> واحد في مصدر الصفحة. ذلك السطر وحده يحدد ما إذا كان طلبك إلى CaptchaAI يحتاج المعامل enterprise=1 أم لا.
كل ما عداه متطابق: نقطة النهاية، والطريقة userrecaptcha، ودورة الاستطلاع، وحقل g-recaptcha-response الذي يستقبل الرمز. لذلك يبدأ هذا الدليل من قراءة مصدر الصفحة، ثم ينتقل إلى جدول الفروق وأمثلة الإرسال للمسارين.
الخلاصة قبل التفاصيل
- كلا الإصدارين يعمل بلا واجهة مرئية، ويعيد درجة بين 0.0 و1.0 يقيّمها الموقع لا أنت.
- الكشف يعتمد على ملف الـ JavaScript:
api.js?render=KEYمقابلenterprise.js?render=KEY. - أضِف
enterprise=1مع Enterprise فقط، وبقية المعاملات كما هي. - معامل
actionمطلوب في الحالتين، وقيمته الخاطئة تخفض الدرجة.
كيف تعرف أي إصدار من reCAPTCHA v3 يعمل على الصفحة
ابدأ من مصدر الصفحة قبل إرسال أي طلب. ثلاث طرق تغطي أغلب الحالات: فحص من Python أثناء التشغيل، فحص مكافئ من Node.js داخل خط الأتمتة، وفحص يدوي من DevTools عند معاينة موقع جديد.
فحص من Python — يحدد الإصدار ويستخرج مفتاح الموقع ومعامل الإجراء دفعة واحدة:
import requests
import re
def detect_v3_type(url):
resp = requests.get(url)
html = resp.text
# Check for enterprise.js
if "enterprise.js" in html:
version = "enterprise_v3"
execute_fn = "grecaptcha.enterprise.execute"
elif "recaptcha/api.js" in html and "render=" in html:
version = "standard_v3"
execute_fn = "grecaptcha.execute"
else:
return None
# Extract sitekey from render parameter
key_match = re.search(r'render[=:]\s*["\']?([A-Za-z0-9_-]{40})', html)
sitekey = key_match.group(1) if key_match else None
# Extract action parameter
action_match = re.search(r'action["\']?\s*[:=]\s*["\'](\w+)', html)
action = action_match.group(1) if action_match else "unknown"
return {
"version": version,
"sitekey": sitekey,
"action": action,
"execute_fn": execute_fn
}
info = detect_v3_type("https://example.com/login")
print(info)
فحص مكافئ من Node.js لخطوط الأتمتة المبنية على Axios أو Puppeteer:
const axios = require("axios");
async function detectV3Type(url) {
const { data: html } = await axios.get(url);
let version, executeFn;
if (html.includes("enterprise.js")) {
version = "enterprise_v3";
executeFn = "grecaptcha.enterprise.execute";
} else if (html.includes("recaptcha/api.js") && html.includes("render=")) {
version = "standard_v3";
executeFn = "grecaptcha.execute";
} else {
return null;
}
const keyMatch = html.match(/render[=:]\s*['"]?([A-Za-z0-9_-]{40})/);
const actionMatch = html.match(/action['"]?\s*[:=]\s*['"](\w+)/);
return {
version,
sitekey: keyMatch?.[1] || null,
action: actionMatch?.[1] || "unknown",
executeFn,
};
}
فحص يدوي من وحدة تحكم المتصفح حين تعاين موقعاً جديداً بسرعة:
// Paste in DevTools console
if (document.querySelector('script[src*="enterprise.js"]')) {
console.log("Enterprise v3");
console.log("Execute:", typeof grecaptcha?.enterprise?.execute);
} else if (document.querySelector('script[src*="api.js"][src*="render="]')) {
console.log("Standard v3");
console.log("Execute:", typeof grecaptcha?.execute);
}
جدول الفروق: reCAPTCHA v3 القياسي مقابل Enterprise
| البند | القياسي v3 | Enterprise v3 |
|---|---|---|
| تشغيل بلا واجهة مرئية | نعم | نعم |
| درجة المخاطرة 0.0–1.0 | نعم | نعم |
معامل action |
مطلوب | مطلوب |
| ملف JavaScript | api.js?render=KEY |
enterprise.js?render=KEY |
| دالة التنفيذ | grecaptcha.execute() |
grecaptcha.enterprise.execute() |
| رموز الأسباب | لا | نعم — AUTOMATION، TOO_MUCH_TRAFFIC |
| حدود مخصصة لكل إجراء | لا | نعم — عبر Google Cloud Console |
| كشف تسرّب كلمات المرور | لا | نعم |
| Account Defender | لا | نعم |
| نقطة نهاية التحقق | siteverify — مجانية |
recaptchaenterprise.googleapis.com — مدفوعة |
| معاملات CaptchaAI | version=v3 |
version=v3 + enterprise=1 |
| زمن الحل لدى CaptchaAI | < 4 ثوانٍ | < 4 ثوانٍ |
حل الإصدارين عبر CaptchaAI بالمسار نفسه
المسار القياسي: version=v3 وحده
أرسل الطلب إلى in.php، احفظ معرّف المهمة، ثم استطلع النتيجة من res.php كل خمس ثوانٍ حتى يعود الرمز.
import requests
import time
# Submit
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"action": "login",
"pageurl": page_url
})
task_id = resp.text.split("|")[1]
# Poll
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
مسار Enterprise: أضِف enterprise=1
المعاملات نفسها مع علم واحد إضافي، ودورة الاستطلاع لا تتغيّر إطلاقاً.
import requests
import time
# Submit — add enterprise=1
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"version": "v3",
"enterprise": 1, # Required for Enterprise
"googlekey": sitekey,
"action": "login",
"pageurl": page_url
})
task_id = resp.text.split("|")[1]
# Polling is identical to standard
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY", "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
token = result.text.split("|")[1]
break
حلّال موحّد يكتشف الإصدار تلقائياً
في الإنتاج لا تثبّت الإصدار داخل الكود. اجعل الكشف يعمل مع كل تحميل للصفحة، فقد ينتقل الموقع إلى Enterprise دون إشعار.
import requests
import time
import re
class RecaptchaV3Solver:
def __init__(self, api_key):
self.api_key = api_key
def detect_and_solve(self, page_url, action=None):
"""Auto-detect standard vs enterprise and solve."""
html = requests.get(page_url).text
is_enterprise = "enterprise.js" in html
key_match = re.search(r'render[=:]\s*["\']?([A-Za-z0-9_-]{40})', html)
if not key_match:
raise Exception("No v3 sitekey found")
sitekey = key_match.group(1)
if not action:
action_match = re.search(r'action["\']?\s*[:=]\s*["\'](\w+)', html)
action = action_match.group(1) if action_match else "verify"
params = {
"key": self.api_key,
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"action": action,
"pageurl": page_url
}
if is_enterprise:
params["enterprise"] = 1
resp = requests.get("https://ocr.captchaai.com/in.php", params=params)
if not resp.text.startswith("OK|"):
raise Exception(f"Submit failed: {resp.text}")
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key, "action": "get", "id": task_id
})
if result.text.startswith("OK|"):
return result.text.split("|")[1]
if result.text != "CAPCHA_NOT_READY":
raise Exception(f"Solve failed: {result.text}")
raise Exception("Timed out")
solver = RecaptchaV3Solver("YOUR_API_KEY")
token = solver.detect_and_solve("https://example.com/login", action="login")
print(f"Token: {token[:40]}...")
معامل action: من أين تستخرجه ولماذا يهمّ
معامل action مطلوب في الإصدارين. القيمة الخاطئة لا تمنع الحل، لكنها تخفض الدرجة على جانب الموقع فيُرفض الرمز عند التحقق. استخرج السلسلة الدقيقة من نصوص الصفحة بدل تخمينها.
import re
def find_v3_actions(html):
"""Extract all action parameters from page JavaScript."""
# Look for grecaptcha.execute(key, {action: '...'})
pattern = r"(?:grecaptcha\.(?:enterprise\.)?execute|action)\s*[(:]\s*['\"](\w+)"
actions = re.findall(pattern, html)
return list(set(actions))
# Common actions: "login", "submit", "register", "checkout", "homepage"
أخطاء تتكرر عند التبديل بين الإصدارين
| الخطأ | ما يحدث | الإصلاح |
|---|---|---|
إضافة enterprise=1 على صفحة قياسية |
رمز قد يُرفض عند التحقق | تأكد من وجود enterprise.js أولاً |
إغفال enterprise=1 على صفحة Enterprise |
ترفض الواجهة الخلفية الرمز | أضِف العلم عند رصد enterprise.js |
قيمة action خاطئة |
درجة منخفضة ورفض عند التحقق | استخرجها من JavaScript الصفحة |
إغفال version=v3 |
تُعامَل المهمة كأنها v2 | ضمّنه في كل طلب قائم على الدرجة |
| استخدام مفتاح موقع خاص بـ v2 | ERROR_WRONG_GOOGLEKEY |
مفاتيح v3 تأتي من render=KEY |
إدراج الرمز في نموذج الصفحة
الطريقة واحدة في الإصدارين: يُكتب الرمز في الحقل g-recaptcha-response قبل الإرسال، عبر متصفح مؤتمت أو طلب HTTP مباشر.
# For browser-based workflows (Selenium)
driver.execute_script(
f'document.getElementById("g-recaptcha-response").value = "{token}";'
)
# For pure HTTP workflows
requests.post(page_url, data={
"g-recaptcha-response": token,
"username": "user",
"password": "pass"
})
// Puppeteer
await page.evaluate((tok) => {
document.getElementById("g-recaptcha-response").value = tok;
}, token);
// Pure HTTP (axios)
await axios.post(pageUrl, new URLSearchParams({
"g-recaptcha-response": token,
username: "user",
password: "pass",
}));
سيناريو من السوق العربي
فريق تقني في القاهرة يشغّل مراقبة يومية لأسعار الشحن على بوابة لوجستية خليجية. بدأ التكامل على api.js وعمل بثبات لأسابيع، ثم بدأت الرموز تُرفض فجأة دون أي تعديل في الكود. السبب: انتقال البوابة إلى enterprise.js بعد تحديث على جانبها.
الإصلاح كان في سطرين: قراءة مصدر الصفحة عند كل تشغيل، وإضافة enterprise=1 عند رصد الملف. ولأن خطط CaptchaAI تُحسب بعدد الـ Threads المتزامنة لا بعدد عمليات الحل — تبدأ من BASIC بسعر 15 دولاراً شهرياً مع 5 threads وحلول غير محدودة — لم يتغيّر شيء في الفاتورة.
الأسئلة الشائعة
هل أحتاج إلى مشروع Google Cloud لحل reCAPTCHA v3 Enterprise؟
لا. مشروع Google Cloud ونقطة نهاية التحقق المدفوعة تخصّان مالك الموقع لا المُتكامل معه. أنت ترسل مفتاح الموقع وعنوان الصفحة ومعامل الإجراء فقط، وتستقبل الرمز.
رجع الرمز بنجاح لكن الموقع رفضه — أين الخلل؟
راجع ثلاثة عناصر: قيمة action، وعلم enterprise=1 مقابل ملف الـ JavaScript المحمّل، وpageurl هل هو الصفحة التي يُرسل منها النموذج. أي خطأ فيها ينتج رمزاً يسقط عند التحقق.
كيف أفحص الإصدار داخل جلسة Selenium قائمة؟
اقرأ مصدر الصفحة بعد اكتمال التحميل وابحث عن enterprise.js مباشرة:
page_source = driver.page_source
is_enterprise = "enterprise.js" in page_source
ما الفرق عند الإرسال بين reCAPTCHA v2 Enterprise و v3 Enterprise؟
كلاهما يستخدم الطريقة userrecaptcha مع enterprise=1، لكن v3 يتطلب version=v3 ومعامل action، بينما v2 Enterprise لا يحتاج إلى درجة ولا إجراء.