المشاكل الشائعة

حلول للمشاكل الأكثر شيوعاً عند استخدام FourA API.

محتوى فارغ أو غير مكتمل

العَرَض: تُرجع الـ API حالة 200 ولكن الحقل data فارغ أو يفتقد المحتوى المتوقع.

السبب: تستخدم الصفحة المستهدفة JavaScript لعرض المحتوى بعد التحميل الأولي للصفحة.

الحل: قم بالتبديل من الـ endpoint المفرد إلى الـ endpoint الخاص بالمتصفح. استخدم checkText للتحقق من تحميل المحتوى:

curl -X POST https://eu.api.foura.ai/api/browser/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/products",
    "timeout_ms": 15000,
    "checkText": "product-list"
  }'

ملاحظة: يُرجع الـ endpoint الخاص بالمتصفح المحتوى في الحقل body (وليس data).

صفحات 403 Forbidden أو CAPTCHA

العرض: تُرجع الـ API رمز HTML يحتوي على تحدي CAPTCHA أو صفحة رفض الوصول.

السبب: اكتشف الموقع المستهدف أن الـ request آلي وقام بحظره.

الحل: استخدم الـ endpoint الخاص بـ proxy للتدوير التلقائي لعناوين IP:

curl -X POST https://eu.api.foura.ai/api/proxy/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "maxTries": 5,
    "request": {
      "method": "GET",
      "url": "https://example.com/prices",
      "unblocker": true
    }
  }'

إذا استمرت المشكلة، قم بزيادة maxTries لمنح تدوير الـ proxy المزيد من المحاولات.

أخطاء انتهاء المهلة

العرض: تفشل الطلبات مع خطأ انتهاء المهلة.

السبب: تستغرق الصفحة المستهدفة وقتا أطول للتحميل من المهلة الزمنية المحددة.

الحل: قم بزيادة timeout_ms (الافتراضي هو 15s للـ single، و30s للـ browser، و45s للـ proxy):

curl -X POST https://eu.api.foura.ai/api/browser/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://slow-site.com",
    "timeout_ms": 60000
  }'

بالنسبة لطلبات المتصفح، تحقق أيضا من أن قيمة checkText تظهر بالفعل في الصفحة. سيؤدي أي خطأ مطبعي دائما إلى انتهاء المهلة.

429 طلبات كثيرة جدا (حد RPM)

العرض: تُرجع الـ API الحالة 429 مع رسالة "rate limit exceeded".

السبب: لقد تجاوزت حد الطلبات في الدقيقة (RPM). هذا يختلف عن حدود التزامن (انظر 503 أدناه).

الحل: استخدم الحقل retryAfter من الاستجابة للانتظار المقدار المناسب من الوقت قبل إعادة المحاولة:

import time
import requests

def make_request(endpoint_url, payload, retries=3):
    for i in range(retries):
        resp = requests.post(
            endpoint_url,
            headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
            json=payload
        )
        if resp.status_code == 429:
            body = resp.json()
            wait = body.get("retryAfter", 2 ** i)
            time.sleep(wait)
            continue
        return resp
    raise Exception("Rate limit not resolved after retries")

# Example: single request
make_request(
    "https://eu.api.foura.ai/api/single/",
    {"method": "GET", "url": "https://example.com"}
)

تحقق من استخدامك الحالي في Dashboard لمعرفة rate limits الخاصة بك.

503 الخدمة غير متوفرة

العرض: تُرجع API حالة 503.

السبب: يحدث هذا في حالتين:

  1. الوصول إلى حد التزامن. لديك عدد كبير جدًا من الـ requests المتزامنة قيد التشغيل. هذا يختلف عن 429، والذي يحد من الـ requests في الدقيقة. مع 503، لم تتجاوز RPM الخاص بك، ولكنك وصلت للحد الأقصى لعدد الـ requests التي يمكن تشغيلها في نفس الوقت.
  2. الخدمة معطلة مؤقتًا. هناك صيانة قيد الإجراء.

تتضمن كلتا الحالتين حقل retryAfter في الـ response.

الحل: انتظر لمدة retryAfter ثوانٍ، ثم أعد المحاولة:

import time
import requests

def make_request_with_retry(endpoint_url, payload, retries=3):
    for i in range(retries):
        resp = requests.post(
            endpoint_url,
            headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
            json=payload
        )
        if resp.status_code in (429, 503):
            body = resp.json()
            wait = body.get("retryAfter", 2 ** i)
            time.sleep(wait)
            continue
        return resp
    raise Exception("Request not resolved after retries")

إذا كنت تواجه حدود التزامن 503 بانتظام، فقم بتقليل عدد الطلبات المتوازية في مسار استخراج البيانات الخاص بك، أو تحقق من حد التزامن الخاص بخطتك في لوحة التحكم.

504 مهلة المنبع (Upstream Timeout)

الأعراض: تُرجع الـ API رمز 504 مع {"error": "Upstream timeout"}.

السبب: لم يكتمل العمل ضمن الوقت المخصص الذي حددته للطلب (request). يمكن أن يحدث هذا بسبب هدف بطيء، أو حل تحدٍ أولي، أو صفحة كبيرة جدا. إنها ليست مشكلة في مفتاحك، أو معلماتك، أو الـ proxy الخاص بك.

الحل: امنح الاستدعاء المزيد من الوقت، أو أعد المحاولة. تنتظر FourA الـ timeout_ms الخاص بك بالإضافة إلى هامش صغير، لذا فإن زيادته يمدد فترة الانتظار فعليا:

{
  "url": "https://slow-site.com/report",
  "timeout_ms": 90000
}

بالنسبة إلى /api/auto/ على هدف محمي، قد يستغرق الاتصال الأول البارد عشرات الثواني. يغطي timeout_ms الخاص به السلم بأكمله ويقبل حتى 180000.

502 خادم Upstream غير متوفر

العَرَض: تُرجع الـ API الخطأ 502 مع {"error": "Upstream unavailable"}، أو الخطأ 503 مع {"error": "Backend service unavailable"}.

السبب: وصل FourA إلى محركه الخاص ولكنه لم يتمكن من استخدام الرد، وعادة ما يكون ذلك بسبب إعادة تشغيل إحدى النسخ (instance).

الحل: أعد المحاولة مع فترة تأخير قصيرة. يصنف كلاهما كـ service_error، ويتم فوترة success فقط، لذا لا تكلفك إعادة المحاولة أي رسوم إضافية. إذا استمرت المشكلة لأكثر من دقيقة أو دقيقتين، فتحقق من صفحة الحالة.

401 أخطاء المصادقة

العَرَض: يُرجع كل طلب خطأ 401 غير مصرح به (Unauthorized).

قائمة التحقق:

  1. تحقق من أن الترويسة (header) هي X-API-Key: YOUR_API_KEY (وليس Authorization: Bearer أو Api-Key)
  2. تحقق من عدم وجود مسافات إضافية أو أسطر جديدة في مفتاح الـ API الخاص بك
  3. قم بإنشاء مفتاح جديد من لوحة التحكم إذا كان من المحتمل أن يكون المفتاح الحالي مخترقًا

400 الهدف يحل إلى IP خاص/محجوز

العَرَض: تُرجع الـ API الخطأ 400 مع Target <ip> resolves to a private/reserved IP قبل أن يغادر الطلب شبكة FourA.

السبب: يحل url الخاص بك إلى نطاق IP خاص، أو استرجاعي (loopback)، أو محجوز (RFC 5735 أو RFC 6598 أو كتل عناوين IPv6 المحجوزة). يرفض FourA هذه الأهداف حتى لا يمكن استخدام شبكته للوصول إلى المضيفين الداخليين.

الحل: قم بجلب URL عام. إذا كنت تقوم بالاختبار، فاستخدم هدفًا عامًا مثل https://example.com أو https://httpbin.org/get. إذا كان هدفك المقصود هو خدمة تقوم بتشغيلها، فاعرضها على اسم مضيف عام (public hostname) أولاً.

{ "error": "Target <ip> resolves to a private/reserved IP" }

no_eligible_proxy عند استخدام exitCountries

العرض: يُرجع استدعاء /api/proxy/ مع exitCountries رمز HTTP 200 مع غلاف خطأ JSON:

{
  "error": "No eligible proxy found for exit countries: CZ, GB",
  "code": "no_eligible_proxy",
  "details": { "exitCountries": ["CZ", "GB"] },
  "total": 0.084
}

السبب: لا يحتوي تجمع proxy الحالي على مخرج عامل يتطابق بلده المرئي للهدف مع قائمة السماح الخاصة بك. لا تتراجع FourA أبدا إلى بلد غير مطلوب عند تعيين exitCountries.

الحل: احتفظ بالنطاق المطلوب وأعد المحاولة لاحقا. يتم تحديث التجمع كل 10 دقائق تقريبا، لذا فإن البلد الذي ليس له تطابق الآن غالبا ما يحصل على تطابق في غضون ساعة.

import time, requests

def fetch_scoped(url, countries, max_attempts=6, wait_sec=600):
    for _ in range(max_attempts):
        r = requests.post("https://eu.api.foura.ai/api/proxy/",
            headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
            json={"maxTries": 5, "exitCountries": countries,
                  "request": {"method": "GET", "url": url}}).json()
        if r.get("code") == "no_eligible_proxy":
            time.sleep(wait_sec)
            continue
        return r
    raise RuntimeError(f"no eligible exit in {countries} after {max_attempts} attempts")

لا تقم بتوسيع قائمة البلدان إلا إذا تغيرت متطلبات البلد في سير عملك فعليا. يمكن أن تؤدي التراجعات الصامتة إلى بلدان أخرى إلى تعطيل المنطق المعتمد على الموقع الجغرافي في المراحل اللاحقة.

عودة Response Body كنص مشوه

العَرَض: يحتوي data (أو body) الخاص بالاستجابة على أحرف مشوهة أو غير مقروءة عندما يستخدم الهدف مجموعة أحرف غير UTF-8.

السبب: افتراضيا، يقوم FourA بفك تشفير نصوص الاستجابة تلقائيا إلى UTF-8 بناء على ترويسة Content-Type الخاصة بالهدف أو وسم HTML <meta charset>. إذا قدم الهدف معلومات غير صحيحة حول مجموعة الأحرف الخاصة به، فستحصل على نص مشوه.

الحل: بالنسبة للحمولات الثنائية (الصور، protobuf، الصوت الخام)، قم بتعيين returnBuffer: true في الـ request. سيعود النص كعازل base64 دون تطبيق أي تحويل لمجموعة الأحرف.

{
  "method": "GET",
  "url": "https://example.com/image.png",
  "returnBuffer": true
}

بالنسبة للأهداف النصية التي تعلن عن charset خاطئ، قم بفك تشفير البايتات الخام بنفسك: اجلب باستخدام returnBuffer: true، وقم بفك تشفير base64، ثم طبق charset الصحيح.

HTML غير متوقع بدلاً من JSON

الأعراض: كنت تتوقع JSON من الموقع المستهدف لكنك تلقيت HTML.

السبب: قد تقدم الصفحة المستهدفة محتوى مختلفًا بناءً على الـ headers.

الحل: أضف header Accept وقم بتمكين unblocker للحصول على headers متصفح واقعية:

curl -X POST https://eu.api.foura.ai/api/single/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "method": "GET",
    "url": "https://api.example.com/data",
    "headers": [["Accept", "application/json"]],
    "unblocker": true
  }'

يمكنك أيضًا ضبط tryJsonData على true لجعل FourA يحلل ردود JSON تلقائيًا.

النص عبارة عن صفحة تحدي، وليس محتوى

الأعراض: نجح الاستدعاء، وstatus هو 200، لكن data (أو body) عبارة عن فحص روبوت بدلاً من الصفحة التي أردتها.

السبب: أجرى الهدف فحصًا للروبوت استوفاه FourA لكنه لم يتمكن من تجاوزه. يشير الرد إلى ذلك: يُرجع Single و Proxy defense مع solved: false، ويُرجع Browser defenseSolved: false مع المورد في defenses.present.

الحل: تحقق من defense.vendor أولاً، ثم صعد الأمر. جرب ملف تعريف متصفح مختلفًا على Single، أو انتقل إلى Proxy للحصول على مخرج مختلف، أو استخدم Browser حتى يتم تشغيل JavaScript. مرجع الحقل الكامل وقائمة الموردين: دفاعات مكافحة الروبوتات.

أضف سلسلة فرعية validate.data.accept تحملها الصفحة الحقيقية فقط. بدونها، تعتبر صفحة التحدي التي يتم إرجاعها باستخدام HTTP 200 نجاحًا، وتكتشف ذلك في المراحل التالية بدلاً من الاستدعاء.

ما زلت عالقًا؟

إذا لم ينجح أي من الحلول المذكورة أعلاه:

  1. تحقق من صفحة الحالة بحثًا عن أي حوادث جارية
  2. راجع مقاييس طلبك في لوحة المعلومات
  3. اتصل بالدعم على support@foura.ai مع تفاصيل طلبك (قم بتضمين X-FourA-Request-Id من الاستجابة الفاشلة)

الخطوات التالية

آخر تحديث: 12 أغسطس 2026