يبدأ حلّ Cloudflare Turnstile بقيمتين فقط: مفتاح الموقع (sitekey) ورابط الصفحة التي تظهر فيها الأداة. متى توفّرت هاتان القيمتان، يتكفّل CaptchaAI بالباقي ويعيد إليك رمزًا صالحًا. العقبة الوحيدة عمليًا هي العثور على مفتاح الموقع، فهو لا يظهر دائمًا في المكان نفسه: أحيانًا يُكتب صراحةً داخل وسم HTML، وأحيانًا يُحقَن عبر JavaScript، وأحيانًا لا تجده إلا داخل رابط الـ iframe بعد أن تُعرض الأداة. يشرح هذا الدليل الأماكن الثلاثة التي يسكنها المفتاح، وكيف تستخرجه من كلٍّ منها، ثم كيف تمرّره إلى CaptchaAI للحصول على الرمز وحقنه في الصفحة.
أين يختبئ مفتاح موقع Turnstile؟
قبل كتابة أي سطر برمجي، من المفيد معرفة الأماكن الثلاثة التي يظهر فيها مفتاح الموقع، لأن ترتيب البحث فيها يوفّر عليك وقتًا:
- سمة
data-sitekeyعلى عنصر.cf-turnstile— أوضح مكان وأسرعه، ولا يتطلّب تشغيل JavaScript. - استدعاء
turnstile.render()داخل شيفرة الصفحة — حين تُبنى الأداة برمجيًا بدل كتابتها في HTML. - رابط
srcالخاص بإطار iframe الذي يعرضه Turnstile — الملاذ الأكثر موثوقية، لأن المفتاح يكون حاضرًا حتمًا في الرابط بمجرد أن تُعرض الأداة.
القاعدة العملية: جرّب سمة data-sitekey أولًا لأنها الأرخص، فإن لم تجدها فتّش عن استدعاء turnstile.render، وإن أخفق الاثنان فارجع إلى رابط الـ iframe بعد تحميل الصفحة في متصفح بلا واجهة. لكل صفحة، واحدة على الأقل من هذه الطرق الثلاث ستنجح.
الطريقة الأولى: قراءة سمة data-sitekey من DOM
في معظم المواقع يُكتب مفتاح الموقع مباشرةً داخل الصفحة على هيئة سمة data-sitekey. هذا هو المسار الأسرع: سطر واحد في وحدة تحكّم المتصفح يكشف كل أدوات Turnstile الموجودة ومعها قيمها المصاحبة مثل data-action وdata-theme.
// Browser console
document.querySelectorAll('.cf-turnstile').forEach((el, i) => {
console.log(`Turnstile ${i}:`, {
sitekey: el.getAttribute('data-sitekey'),
action: el.getAttribute('data-action'),
cData: el.getAttribute('data-cdata'),
theme: el.getAttribute('data-theme'),
});
});
Python — من HTML الثابت
إذا كانت الأداة مكتوبة في HTML الأولي للصفحة، فيكفي جلب الصفحة عبر requests ثم البحث عن السمة بتعبير نمطي، دون الحاجة إلى متصفح كامل:
import re
import requests
html = requests.get("https://example.com/login").text
matches = re.findall(
r'class=["\'][^"\']*cf-turnstile[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)',
html
)
for sk in matches:
print(f"Sitekey: {sk}")
Python مع Selenium
أما إذا كانت الصفحة تعتمد على JavaScript لبناء واجهتها، فاستخدم Selenium كي تنتظر اكتمال العرض ثم تقرأ السمة من العنصر الحيّ:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com/login")
widgets = driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile")
for w in widgets:
sitekey = w.get_attribute("data-sitekey")
action = w.get_attribute("data-action")
print(f"Sitekey: {sitekey}, Action: {action}")
الطريقة الثانية: اعتراض استدعاء turnstile.render
كثير من المواقع لا تكتب data-sitekey في HTML، بل تُنشئ الأداة برمجيًا عبر استدعاء turnstile.render() وتمرّر إليه المفتاح ضمن كائن الإعدادات:
turnstile.render('#captcha-container', {
sitekey: '0x4AAAAAAAB...',
callback: function(token) {
document.getElementById('cf-token').value = token;
},
});
يمكنك التقاط المفتاح من مصدر الصفحة مباشرةً بتعبير نمطي يبحث عن الاستدعاء ويستخرج قيمة sitekey من داخله:
# Find turnstile.render calls
render_match = re.search(
r'turnstile\.render\s*\([^,]*,\s*\{([^}]+)\}',
html
)
if render_match:
config = render_match.group(1)
sk = re.search(r'sitekey\s*:\s*["\']([^"\']+)', config)
if sk:
print(f"Sitekey from render: {sk.group(1)}")
الاعتراض عبر Puppeteer
حين يُحمَّل المفتاح ديناميكيًا ولا يظهر في المصدر الثابت، اعترض الاستدعاء نفسه قبل تحميل الصفحة. تلتفّ الشيفرة التالية حول دالة turnstile.render وتسجّل كل الإعدادات الممرَّرة إليها، بما فيها مفتاح الموقع:
// Intercept turnstile.render before page loads
await page.evaluateOnNewDocument(() => {
window.__turnstileParams = [];
const origRender = window.turnstile?.render;
Object.defineProperty(window, 'turnstile', {
set(val) {
this._turnstile = val;
const orig = val.render;
val.render = function(container, params) {
window.__turnstileParams.push(params);
console.log('Turnstile render:', JSON.stringify(params));
return orig.apply(this, arguments);
};
},
get() { return this._turnstile; }
});
});
await page.goto('https://example.com/login', { waitUntil: 'networkidle2' });
const params = await page.evaluate(() => window.__turnstileParams);
console.log('Captured Turnstile params:', params);
الطريقة الثالثة: قراءة مفتاح الموقع من رابط iframe
بمجرد أن يُعرض Turnstile فعليًا، يحمّل إطار iframe من نطاق challenges.cloudflare.com، ويحمل رابط هذا الإطار مفتاح الموقع ضمن معاملاته. هذه الطريقة هي شبكة الأمان: إن أخفقت الطريقتان السابقتان، فالمفتاح موجود هنا حتمًا:
document.querySelectorAll('iframe').forEach(iframe => {
if (iframe.src.includes('challenges.cloudflare.com')) {
console.log('Turnstile iframe:', iframe.src);
const match = iframe.src.match(/sitekey=([A-Za-z0-9_-]+)/);
if (match) console.log('Sitekey:', match[1]);
}
});
سيناريو عملي: بوابة حجز إقليمية
تخيّل فريق ضمان جودة في متجر إلكتروني خليجي يريد اختبار مسار إتمام الشراء آليًا كل ليلة. صفحة تسجيل الدخول محميّة بـ Turnstile في وضعه «المُدار»، فلا يظهر مربّع تحقّق واضح للمستخدم. عند تشغيل سكربت الأتمتة يفشل الطلب لأن حقل cf-turnstile-response يبقى فارغًا. الحل هو استخراج مفتاح الموقع مرة واحدة بإحدى الطرق الثلاث أعلاه، وتخزينه في متغيّرات البيئة، ثم استدعاء CaptchaAI في كل تشغيل للحصول على رمز طازج وحقنه قبل إرسال النموذج. بهذا يبقى اختبار الليلة مستقرًا دون تدخّل بشري، وتُقاس رحلة الشراء كما يعيشها الزبون الحقيقي. لاحظ أن مفتاح الموقع نفسه ثابت لكل صفحة، بينما الرمز الناتج مؤقّت ويجب توليده في كل مرة.
حل Turnstile باستخدام CaptchaAI
بعد أن يصبح مفتاح الموقع ورابط الصفحة بين يديك، يتحوّل الحل إلى نداءين للـ API: أرسل المهمة إلى in.php مع method=turnstile، ثم استطلِع النتيجة من res.php حتى يعود الرمز. يحل CaptchaAI اختبارات Turnstile عادةً خلال أقل من 10 ثوانٍ مع معدل نجاح مرتفع على الأنواع المدعومة.
Python
import requests
import time
API_KEY = "YOUR_API_KEY"
SITEKEY = "0x4AAAAAAAB..."
PAGE_URL = "https://example.com/login"
# Submit
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"sitekey": SITEKEY,
"pageurl": PAGE_URL,
"json": "1",
}).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
# Poll
for _ in range(24):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
token = result["request"]
print(f"Turnstile token: {token[:50]}...")
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
JavaScript
const axios = require('axios');
const submit = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: 'YOUR_API_KEY',
method: 'turnstile',
sitekey: '0x4AAAAAAAB...',
pageurl: 'https://example.com/login',
json: 1,
}
});
const taskId = submit.data.request;
// Poll for result
let token = null;
for (let i = 0; i < 24; i++) {
await new Promise(r => setTimeout(r, 5000));
const poll = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: 'YOUR_API_KEY', action: 'get', id: taskId, json: 1 }
});
if (poll.data.status === 1) {
token = poll.data.request;
break;
}
}
console.log(`Token: ${token.substring(0, 50)}...`);
حقن الرمز في الصفحة
الرمز وحده لا يكفي؛ يجب وضعه حيث يتوقّعه الموقع. يخزّن Turnstile رمزه في حقل مخفي اسمه cf-turnstile-response، وكثير من عمليات التنفيذ تنتظر أيضًا استدعاء دالة data-callback. لذلك اضبط قيمة الحقل واستدعِ دالة رد النداء معًا لضمان قبول النموذج:
# Selenium
driver.execute_script("""
const input = document.querySelector('input[name="cf-turnstile-response"]');
if (input) input.value = arguments[0];
// Also set in the Turnstile widget's callback
const widget = document.querySelector('.cf-turnstile');
const callbackName = widget?.getAttribute('data-callback');
if (callbackName && typeof window[callbackName] === 'function') {
window[callbackName](arguments[0]);
}
""", token)
استكشاف الأخطاء وإصلاحها
| المشكلة | السبب المحتمل | الحل |
|---|---|---|
لا يُعثر على عنصر .cf-turnstile |
الأداة تُعرض ديناميكيًا بعد التحميل | انتظر اكتمال تحميل الصفحة أو راقبها عبر MutationObserver |
| مفتاح الموقع يعود فارغًا | يُضبط عبر واجهة JavaScript لا في HTML | فتّش عن turnstile.render داخل ملفات السكربت |
| رفض الموقع للرمز | مفتاح الموقع أو رابط الصفحة غير مطابق | تأكّد من تطابق القيمتين تمامًا مع الموقع المستهدف |
خطأ في معامل method |
استخدام userrecaptcha بدل نوع Turnstile |
مرّر method=turnstile في الطلب |
الأسئلة الشائعة
هل مفتاح الموقع سرّي أو يجب إخفاؤه؟
مفتاح الموقع (sitekey) ليس سرًّا؛ فهو معرّف عام يُرسَل إلى المتصفح ويظهر في شيفرة الصفحة، بعكس المفتاح السرّي الذي يبقى على خادم الموقع. لذلك قراءته واستخراجه لأغراض الاختبار أمر طبيعي ولا يكشف بيانات حسّاسة.
هل يتغيّر مفتاح الموقع مع كل زيارة؟
لا؛ مفتاح الموقع ثابت لكل نطاق أو صفحة ولا يتبدّل بين الزيارات، لذا يمكنك استخراجه مرة واحدة وإعادة استخدامه. المتغيّر هو الرمز الناتج عن الحل، فهو مؤقّت وينتهي بسرعة ويجب توليده في كل جلسة.
ماذا أفعل إذا احتوت الصفحة على أكثر من أداة Turnstile؟
حين تحمل الصفحة أكثر من أداة، يعيد المحدّد .cf-turnstile قائمة بكل العناصر. مُرّ على القائمة واقرأ data-sitekey وdata-action من كل عنصر على حدة، فقد يختلف المفتاح أو الإجراء بين أداة وأخرى، ثم أرسل كل واحدة كمهمة منفصلة إلى CaptchaAI.
كم يكلّف حل Turnstile عبر CaptchaAI؟
يعتمد CaptchaAI على تسعير قائم على الـ Threads لا على الدفع لكل عملية حل: تبدأ باقة BASIC من 15 دولارًا شهريًا مع 5 Threads وحلول غير محدودة لكل Thread، وترتفع الباقات حتى VIP-3 بسعر 7,500 دولار و5,000 Thread للأحجام الكبيرة. أي أن كلفة حل Turnstile محكومة بعدد الطلبات المتزامنة لا بعدد الاختبارات.
ابدأ الآن مع CaptchaAI
أنشئ حساب CaptchaAI واحصل على مفتاح الـ API من captchaai.com، ثم طبّق أمثلة الحل أعلاه على أول مفتاح موقع تستخرجه.