أرسلت مهمة حل reCAPTCHA أو Cloudflare Turnstile عبر CaptchaAI فجاءك الرد ERROR_PAGEURL؟ السبب دائماً واحد: قيمة pageurl التي أرسلتها لا تشير إلى الصفحة نفسها التي يظهر فيها اختبار CAPTCHA. الحل المباشر هو نسخ الرابط كاملاً من شريط عنوان المتصفح في اللحظة التي تشاهد فيها الاختبار، ثم إرساله كما هو دون اختصار أو تعديل.
يتحقق مزوّد الحل من صحة الرمز الناتج مقابل المجال الأصلي (origin domain) الذي جرى تحميل الاختبار عليه. فإذا لم يتطابق pageurl مع هذا المجال، يرفض النظام الطلب قبل أن يبدأ الحل أصلاً. لهذا يعتبر ضبط الرابط الصحيح أول خطوة في أي تكامل ناجح، وليس تفصيلاً ثانوياً.
لماذا يظهر خطأ ERROR_PAGEURL؟
اختبار CAPTCHA ليس مجرد صورة أو مربع اختيار؛ إنه مرتبط بمفتاح الموقع (sitekey) وبالمجال الذي صدر له. عندما تُرسل الطلب إلى CaptchaAI، فأنت تخبر الخدمة بأمرين: أين يوجد الاختبار (pageurl) وما مفتاح الموقع الخاص به (googlekey أو sitekey). إذا اختلف الرابط الذي أرسلته عن الرابط الحقيقي — ولو في البروتوكول أو بادئة www — فقد ينتج رمز لا يقبله الموقع المستهدف، أو يُرفض الطلب مباشرةً برمز ERROR_PAGEURL.
الفكرة الجوهرية: الرابط الذي تراه في شريط العنوان هو المرجع، وليس رابط الـ API الذي يستقبل بيانات النموذج، ولا رابط الـ iframe الذي يستضيف الاختبار.
الأسباب الأكثر شيوعاً لعدم تطابق الرابط
| السبب | مثال |
|---|---|
| غياب البروتوكول | example.com بدلاً من https://example.com |
| مجال غير مطابق | www.example.com مقابل example.com |
| إعادة توجيه غيّرت الرابط | نموذج على /login أُعيد توجيهه إلى /auth/login |
| عدم تطابق مسار SPA | مسار JavaScript على /app/login لا يطابق رابط الخادم |
| مشكلات ترميز الرابط | مسافات أو أحرف خاصة غير مشفّرة |
| iframe من مجال مختلف | تحميل الاختبار من نطاق فرعي |
يكفي واحد من هذه الأسباب لإظهار الخطأ. لذا عند التشخيص، قارن الرابط الذي أرسلته حرفاً بحرف مع ما يظهر في المتصفح.
القاعدة الأساسية: انسخ الرابط من شريط العنوان
استخدم الرابط الظاهر في شريط عنوان المتصفح حيث يكون اختبار CAPTCHA مرئياً — بالبروتوكول الكامل وبنفس صيغة المجال تماماً:
# WRONG — incomplete URL
pageurl = "example.com/login"
# WRONG — wrong protocol
pageurl = "http://example.com/login"
# CORRECT — full URL with protocol
pageurl = "https://example.com/login"
# CORRECT — with www if that's what the page uses
pageurl = "https://www.example.com/login"
لاحظ أن https وhttp ليسا متكافئين هنا، وأن www.example.com وexample.com مجالان مختلفان من منظور التحقق.
دالة للتحقق من صحة pageurl قبل الإرسال
بدلاً من الاعتماد على النسخ اليدوي، مرّر الرابط عبر دالة تحقق تلتقط الأخطاء الشائعة مبكراً: بروتوكول مفقود، مجال ناقص، أو جزء تجزئة (#) لا يُرسل إلى الخادم:
from urllib.parse import urlparse
def validate_pageurl(url):
"""Validate pageurl before API submission."""
parsed = urlparse(url)
if not parsed.scheme:
raise ValueError(f"Missing protocol: {url}. Use https://")
if parsed.scheme not in ("http", "https"):
raise ValueError(f"Invalid protocol: {parsed.scheme}")
if not parsed.netloc:
raise ValueError(f"Missing domain: {url}")
# Remove fragment (hash) — not sent to server
clean = f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
if parsed.query:
clean += f"?{parsed.query}"
return clean
# Usage
url = validate_pageurl("https://example.com/login#section")
# Returns: "https://example.com/login"
تحويل هذه الدالة إلى جزء ثابت من سكربت الأتمتة يقلّل تذاكر الدعم المتكررة الناتجة عن أخطاء بسيطة في الرابط.
متابعة عمليات إعادة التوجيه
كثير من صفحات تسجيل الدخول تُعيد التوجيه بعد أول طلب. إذا رمّزت الرابط الأصلي يدوياً، فقد ترسل رابطاً لم يعد يعرض الاختبار. اتبع سلسلة إعادة التوجيه للحصول على الرابط النهائي الفعلي:
import requests
def get_final_url(url):
"""Follow redirects to get the actual page URL."""
resp = requests.get(url, allow_redirects=True, timeout=15)
return resp.url
# If the login page redirects
original = "https://example.com/login"
final = get_final_url(original)
print(f"Final URL: {final}")
# Use final URL as pageurl
استخدم القيمة الناتجة عن get_final_url() كقيمة pageurl، لا الرابط الأصلي قبل إعادة التوجيه.
تطبيقات الصفحة الواحدة (SPA)
تغيّر تطبيقات SPA الرابط عبر JavaScript دون إعادة تحميل كاملة للصفحة، وهنا يكثر الالتباس. ما يهم هو رابط الصفحة الظاهر في شريط العنوان، لا نقطة نهاية الـ API التي يُرسل إليها النموذج بياناته:
# For SPAs, use the domain root + the route shown in the address bar
# NOT the API endpoint that the form submits to
# WRONG — API endpoint
pageurl = "https://api.example.com/v1/auth/login"
# CORRECT — the page URL shown in browser
pageurl = "https://example.com/login"
القاعدة العملية: لو نسخت الرابط من شريط العنوان وحصلت على https://example.com/login، فهذا هو ما ترسله — حتى لو كان النموذج يخاطب نطاقاً فرعياً مثل api.example.com خلف الكواليس.
اختبارات CAPTCHA داخل iframe
عندما يُحمّل الاختبار داخل إطار iframe من مجال مختلف، استخدم رابط الصفحة الرئيسية التي يظهر عليها الاختبار، لا رابط مصدر الـ iframe نفسه:
# If the CAPTCHA is on the MAIN page
pageurl = "https://example.com/register" # Main page URL
# If the CAPTCHA is in an IFRAME with a different domain
# Still use the main page URL, not the iframe src
pageurl = "https://example.com/register"
# NOT: "https://captcha-frame.example.com/challenge"
هذا الخطأ متكرر مع reCAPTCHA وCloudflare Turnstile معاً، لأن كليهما يعرض واجهته داخل iframe مستضاف على نطاق منفصل.
نموذج إرسال صحيح إلى CaptchaAI
بعد التحقق من الرابط، أرسل المهمة إلى نقطة النهاية in.php. لاحظ استدعاء validate_pageurl() قبل بناء حمولة الطلب:
import requests
# Validate URL first
pageurl = validate_pageurl("https://example.com/login")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "SITE_KEY",
"pageurl": pageurl,
"json": 1,
})
result = resp.json()
if result.get("status") == 1:
print(f"Task ID: {result['request']}")
else:
print(f"Error: {result.get('request')}")
عند نجاح الإرسال تحصل على معرّف المهمة، ثم تستطلع النتيجة عبر res.php. أما إذا عاد ERROR_PAGEURL عند هذه المرحلة، فراجع الرابط قبل أي شيء آخر.
سيناريو عملي: متجر عربي مع إعادة توجيه www
تخيّل متجراً إلكترونياً على النطاق example.sa يستخدم reCAPTCHA v2 في صفحة إنشاء الحساب. يفتح المطوّر الصفحة فيرى في المتصفح https://example.sa/register، فيرسل هذا الرابط بالضبط. لكنه يتلقى ERROR_PAGEURL بشكل متقطّع.
السبب: خادم المتجر يعيد توجيه الزيارات من example.sa إلى www.example.sa، فالرابط الحقيقي الذي يُحمّل عليه الاختبار هو https://www.example.sa/register. بمجرد تمرير الرابط عبر get_final_url() والتقاط الوجهة النهائية، تطابق pageurl مع مجال الرمز واختفى الخطأ. الدرس نفسه ينطبق على النطاقات العربية ونطاقات .eg و.ae وأي موقع يفرض بادئة www أو يحوّل http إلى https تلقائياً.
جدول تشخيص سريع
| المشكلة | السبب المحتمل | الإجراء |
|---|---|---|
| خطأ رغم أن الرابط يبدو صحيحاً | عدم تطابق www مقابل غيرها |
طابق شريط العنوان حرفاً بحرف |
| الرابط ينجح أحياناً ويفشل أحياناً | الصفحة تستخدم روابط اختبار A/B | التقط الرابط لحظة الحل |
| تم حل الرمز لكن الموقع رفضه | عدم تطابق مجال pageurl |
يجب أن يطابق مجال الرمز مجال الموقع |
| يعمل في المتصفح ويفشل في الكود | لم تُتابَع إعادة التوجيه | استخدم get_final_url() |
| الرابط يحتوي معلمات استعلام | قد تكون المعلمات مطلوبة | ضمّن معلمات الاستعلام الضرورية |
الأسئلة الشائعة
ما الفرق بين ERROR_PAGEURL وWRONG_GOOGLEKEY؟
يشير ERROR_PAGEURL إلى مشكلة في رابط الصفحة، بينما يشير WRONG_GOOGLEKEY إلى مفتاح موقع غير صحيح. قد يظهران معاً إذا نسخت الاثنين من صفحة خاطئة، لذا تحقق من الرابط ومفتاح الموقع من الصفحة نفسها.
هل يؤثر وجود www أو غيابه على ظهور الخطأ؟
نعم. www.example.com وexample.com مجالان منفصلان من منظور التحقق من الرمز. استخدم دائماً الصيغة التي تظهر فعلياً في شريط العنوان بعد اكتمال إعادة التوجيه.
هل يختلف ضبط pageurl بين reCAPTCHA وCloudflare Turnstile؟
القاعدة واحدة للاثنين: أرسل رابط الصفحة الظاهر في المتصفح، لا رابط الـ iframe. الفارق فقط في اسم حقل المفتاح وفي قيمة method المرسلة إلى الخدمة.
حُلّ الرمز لكن الموقع رفضه، فما السبب؟
غالباً لأن مجال pageurl لا يطابق المجال الذي يتحقق منه الموقع، أو لأن الرمز أُرسل لصفحة مختلفة عن صفحة الحل. تأكد من أن الرابط المستخدم في الإرسال هو نفسه رابط الصفحة التي ستستهلك الرمز.
أدلة ذات صلة
اضبط الرابط الصحيح من أول محاولة — ابدأ الحل مع CaptchaAI.