الانتقال من AZCaptcha إلى CaptchaAI لا يعني إعادة كتابة سكربتاتك من الصفر. تغيّر عنوان النطاق الأساسي ومفتاح الـ API، وتبقى بقية الطلب كما هي؛ فالطرفان يتحدثان لغة API متوافقة مع 2Captcha، ولهذا ينحصر التعديل في سطور معدودة. في الأسطر التالية تجد الخطوات العملية أولاً، ثم جداول المرجع الكامل، وطريقة تشغيل المزوّدَين جنباً إلى جنب قبل تحويل حركة الإنتاج بالكامل.
ما الذي يتغيّر فعلياً في الكود؟
الفكرة كلها تنحصر في تعديلين صغيرين، وكل ما عداهما يبقى على حاله:
- عنوان النطاق الأساسي: من
azcaptcha.comإلىocr.captchaai.comفي نقطتَيin.phpوres.php. - مصدر المفتاح: مفتاح CaptchaAI جديد، ويُفضَّل قراءته من متغيّر بيئة بدل كتابته داخل الملف.
- بقية الطلب: أسماء المعاملات وصيغة الاستجابة ومنطق الاستطلاع الدوري تبقى كما هي.
متى يستحق الانتقال؟
معظم فرق الأتمتة وجمع البيانات في المنطقة العربية تبحث عن أمرين: نتائج مستقرة وتكلفة يمكن التنبؤ بها. إن كنت تشغّل عمليات ليلية لمراقبة الأسعار أو اختبار جودة على متجر إلكتروني، فإن نموذج الدفع لكل عملية حل يجعل فاتورتك تتأرجح مع حجم العمل. يعتمد CaptchaAI بدلاً من ذلك على التسعير حسب عدد الـ Threads المتزامنة مع حلول غير محدودة لكل thread خلال الشهر، وتبدأ الباقات من BASIC بسعر 15 دولاراً شهرياً و5 threads، فتُحسب الميزانية مقدماً بحسب معدل الطلب المتزامن لا بحسب عدد عمليات الحل.
قبل أن تبدّل أي شيء، احسم هذه النقاط:
- الاستقرار: هل يتساوى معدل الحل على بيئتك الفعلية أو يتحسّن؟
- الأنواع: هل النوع الذي تستخدمه فعلاً مدعوم لدى CaptchaAI؟
- التكلفة: هل التسعير حسب الـ Threads أنسب لحجم طلبك المتزامن؟
ملاحظة: لا تحوّل الإنتاج بناءً على انطباع أو على محاولة أو محاولتين؛ اتّخذ القرار من أرقام الاختبار المتوازي في الخطوة الرابعة.
خطوات الانتقال العملية
الخطوة 1: احصل على مفتاح CaptchaAI API
- سجّل حساباً على captchaai.com
- أضف رصيداً إلى حسابك
- انسخ مفتاح الـ API من لوحة التحكم
الخطوة 2: حدّث الكود
التعديل الجوهري سطران: عنوان النطاق ومصدر المفتاح. لاحظ في النسخة "بعد" أننا نقرأ المفتاح من متغيّر بيئة بدل كتابته داخل الملف، وهي عادة أفضل لأمن بيانات الاعتماد.
Python — قبل الانتقال (AZCaptcha)
import requests
API_KEY = "your_azcaptcha_key"
def solve_recaptcha(sitekey, pageurl):
# Submit
resp = requests.post("https://azcaptcha.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data["status"] != 1:
return {"error": data["request"]}
captcha_id = data["request"]
# Poll
import time
for _ in range(60):
time.sleep(5)
result = requests.get("https://azcaptcha.com/res.php", params={
"key": API_KEY, "action": "get", "id": captcha_id, "json": 1
}).json()
if result["status"] == 1:
return {"solution": result["request"]}
if result["request"] != "CAPCHA_NOT_READY":
return {"error": result["request"]}
return {"error": "TIMEOUT"}
Python — بعد الانتقال (CaptchaAI)
import os
import time
import requests
API_KEY = os.environ["CAPTCHAAI_API_KEY"] # Changed: use env var
def solve_recaptcha(sitekey, pageurl):
# Submit — only URL changed
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data.get("status") != 1:
return {"error": data.get("request")}
captcha_id = data["request"]
# Poll — only URL changed
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
JavaScript — قبل الانتقال (AZCaptcha)
const axios = require("axios");
const API_KEY = "your_azcaptcha_key";
async function solveRecaptcha(sitekey, pageurl) {
const submit = await axios.post("https://azcaptcha.com/in.php", null, {
params: { key: API_KEY, method: "userrecaptcha", googlekey: sitekey, pageurl, json: 1 },
});
if (submit.data.status !== 1) return { error: submit.data.request };
const captchaId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await axios.get("https://azcaptcha.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (poll.data.status === 1) return { solution: poll.data.request };
if (poll.data.request !== "CAPCHA_NOT_READY") return { error: poll.data.request };
}
return { error: "TIMEOUT" };
}
JavaScript — بعد الانتقال (CaptchaAI)
const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY; // Changed: env var
async function solveRecaptcha(sitekey, pageurl) {
// Only URLs changed
const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: { key: API_KEY, method: "userrecaptcha", googlekey: sitekey, pageurl, json: 1 },
});
if (submit.data.status !== 1) return { error: submit.data.request };
const captchaId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (poll.data.status === 1) return { solution: poll.data.request };
if (poll.data.request !== "CAPCHA_NOT_READY") return { error: poll.data.request };
}
return { error: "TIMEOUT" };
}
الخطوة 3: اعزل المزوّد خلف واجهة موحّدة
بدل توزيع عنوان النطاق في عشرات الملفات، اجمع منطق الإرسال والاستطلاع في فئة واحدة. عندها يصبح التبديل بين خدمتين مجرّد تغيير سطر واحد، وهو ما يجعل أي انتقال مستقبلي أقل هشاشة:
import os
import time
import requests
class CaptchaProvider:
def __init__(self, base_url, api_key):
self.submit_url = f"{base_url}/in.php"
self.result_url = f"{base_url}/res.php"
self.api_key = api_key
self.session = requests.Session()
def solve(self, sitekey, pageurl, method="userrecaptcha"):
resp = self.session.post(self.submit_url, data={
"key": self.api_key,
"method": method,
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data.get("status") != 1:
return {"error": data.get("request")}
captcha_id = data["request"]
for _ in range(60):
time.sleep(5)
result = self.session.get(self.result_url, params={
"key": self.api_key, "action": "get",
"id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
return {"solution": result["request"]}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
# Switch by changing one line:
# provider = CaptchaProvider("https://azcaptcha.com", "old_key")
provider = CaptchaProvider(
"https://ocr.captchaai.com",
os.environ["CAPTCHAAI_API_KEY"]
)
الخطوة 4: شغّل اختباراً متوازياً
لا تحوّل الإنتاج بناءً على انطباع. شغّل المزوّدَين على الطلبات نفسها وقارن معدل النجاح وزمن الحل على بيئتك الفعلية:
def parallel_test(sitekey, pageurl, runs=10):
azcaptcha = CaptchaProvider("https://azcaptcha.com", "old_key")
captchaai = CaptchaProvider(
"https://ocr.captchaai.com",
os.environ["CAPTCHAAI_API_KEY"]
)
results = {"azcaptcha": [], "captchaai": []}
for i in range(runs):
start = time.time()
az_result = azcaptcha.solve(sitekey, pageurl)
results["azcaptcha"].append({
"success": "solution" in az_result,
"time": time.time() - start
})
start = time.time()
cai_result = captchaai.solve(sitekey, pageurl)
results["captchaai"].append({
"success": "solution" in cai_result,
"time": time.time() - start
})
for provider, data in results.items():
successes = sum(1 for r in data if r["success"])
avg_time = sum(r["time"] for r in data) / len(data)
print(f"{provider}: {successes}/{runs} success, {avg_time:.1f}s avg")
تنبيه منهجي: النتائج تختلف بحسب بيئة التشغيل والحجم والتوقيت. لعيّنة ذات دلالة، شغّل 50 طلباً أو أكثر على النوع الذي يهمّك فعلاً، لا عشرة فقط.
بعد أن تؤكد الأرقام أن CaptchaAI مساوٍ أو أفضل، ارفع نسبة الحركة المحوَّلة تدريجياً حتى تكتمل النقلة.
خريطة نقاط النهاية والمعاملات
نقاط النهاية متطابقة في البنية؛ يتغيّر النطاق فقط. هذا الجدول هو مرجع البحث والاستبدال الأول في مشروعك:
| العملية | AZCaptcha | CaptchaAI |
|---|---|---|
| إرسال المهمة | https://azcaptcha.com/in.php |
https://ocr.captchaai.com/in.php |
| الحصول على النتيجة | https://azcaptcha.com/res.php |
https://ocr.captchaai.com/res.php |
| التحقق من الرصيد | res.php?action=getbalance |
res.php?action=getbalance |
| الإبلاغ عن حل خاطئ | res.php?action=reportbad |
res.php?action=reportbad |
أما المعاملات فالفرق العملي الوحيد فيها هو المفتاح نفسه؛ بنية الطلب تبقى كما هي:
| المعامل | AZCaptcha | CaptchaAI | ملاحظات |
|---|---|---|---|
key |
مفتاح الـ API | مفتاح الـ API | مفتاح مختلف — احصل عليه من captchaai.com |
method |
userrecaptcha |
userrecaptcha |
مطابق |
googlekey |
مفتاح الموقع | مفتاح الموقع | مطابق |
pageurl |
عنوان URL للصفحة | عنوان URL للصفحة | مطابق |
json |
1 |
1 |
مطابق |
proxy |
user:pass@host:port |
user:pass@host:port |
نفس الصيغة |
proxytype |
HTTP/SOCKS5 |
HTTP/SOCKS5 |
مطابق |
قائمة تحقق قبل تحويل الإنتاج
- أنشئ حساب CaptchaAI وموّله ☐
- استبدل عنوان النطاق الأساسي في جميع الملفات ☐
- حدّث مفتاح الـ API (استخدم متغيّر بيئة) ☐
- شغّل اختباراً متوازياً (10 حلول فأكثر) ☐
- قارن معدلات النجاح ☐
- قارن أوقات الحل ☐
- حدّث المراقبة والتنبيهات لنقاط النهاية الجديدة ☐
- بدّل حركة الإنتاج تدريجياً ☐
- راقب لمدة 24 ساعة ☐
- أوقف مفتاح AZCaptcha ☐
معالجة المشكلات الشائعة
قاعدة عامة: سجّل نوع الحل وزمن الاستجابة ورمز الخطأ معاً حتى يكون التشخيص موثوقاً عند أي عطل.
| المشكلة | السبب المحتمل | الإجراء |
|---|---|---|
ERROR_KEY_DOES_NOT_EXIST |
مفتاح API غير صحيح | تحقق من المفتاح المنسوخ من لوحة تحكم CaptchaAI |
ERROR_ZERO_BALANCE |
لا يوجد رصيد في الحساب الجديد | أضف رصيداً على captchaai.com |
| اختلاف رموز الأخطاء بين الخدمتين | فروق طفيفة في تسميات الأخطاء | معظم الرموز متطابقة؛ أنشئ خريطة بسيطة للرموز المختلفة |
| اختلاف معدل الحل | تجمّعات حل مختلفة | شغّل 50 طلباً فأكثر للحصول على مقارنة ذات دلالة |
| الاختبار ينجح لكن الإنتاج يفشل | اختلاف الجلسة أو الرؤوس أو سياق البروكسي | أعد استخدام الشروط التي نجحت في الاختبار داخل سير العمل الفعلي |
عند تكرار أي خطأ، افصل بين ما يخص المفتاح والرصيد وما يخص النوع والمعاملات قبل أن تفتح تذكرة دعم.
أسئلة شائعة
هل يمكن تشغيل AZCaptcha وCaptchaAI جنباً إلى جنب أثناء الترحيل؟
نعم، وهذا هو النهج الموصى به. أبقِ المزوّد القديم يعمل وحوّل نسبة صغيرة من الحركة إلى CaptchaAI أولاً، ثم ارفعها تدريجياً بعد أن تؤكد أرقام الاختبار المتوازي أن النتائج مساوية أو أفضل. الواجهة الموحّدة في الخطوة 3 تجعل هذا التبديل التدريجي أمراً بسيطاً على مرحلتين:
- مرحلة القياس: نسبة صغيرة من الطلبات على CaptchaAI للمقارنة.
- مرحلة التحويل: رفع النسبة تدريجياً حتى 100% ثم إيقاف المفتاح القديم.
ما أنواع CAPTCHA التي يحلّها CaptchaAI؟
يحلّ CaptchaAI اختبارات reCAPTCHA v2 وv3 (بما فيها Enterprise)، وCloudflare Turnstile وCloudflare Challenge، وGeeTest v3، والصور/OCR والشبكة، وBLS. أما hCaptcha وFunCaptcha فغير مدعومَين حالياً، وGeeTest v4 قيد الإضافة. وهناك دعم قيد التجربة (beta) لكل من:
- CaptchaFox
- Friendly Captcha
- Lemin
تأكد من أن النوع المستخدم في مشروعك مدعوم قبل الانتقال.
كيف أتعامل مع اختلاف رموز الأخطاء؟
معظم رموز الأخطاء متطابقة بين الخدمتين لأن كليهما يتبع نمط 2Captcha. تعامَل مع الاختلافات القليلة بخريطة رموز مركزية في الكود بدل التحقق المتناثر، وهكذا يبقى التشخيص واضحاً حتى مع تغيّر المزوّد.
هل تتغير طريقة حساب التكلفة بعد الانتقال؟
نعم، وغالباً لصالح الميزانية. يعتمد CaptchaAI على التسعير حسب عدد الـ Threads المتزامنة مع حلول غير محدودة لكل thread شهرياً، بينما تُحسب كثير من الخدمات لكل عملية حل. تبدأ الباقات من BASIC بسعر 15 دولاراً شهرياً و5 threads، فتصبح التكلفة قابلة للتنبؤ بدل أن تتأرجح مع الحجم.
الخطوات التالية
- البدء السريع مع CaptchaAI: حلّ أول كابتشا في دقائق
- حلّ reCAPTCHA v2 عبر الـ API خطوة بخطوة
- حلّ Cloudflare Turnstile عبر الـ API
- حلّ GeeTest v3 عبر الـ API