# أسباب استنفاد محاولات Proxy Request

> URL: https://foura.ai/ar/docs/troubleshooting/proxy-attempt-report
> Updated: 2026-09-30
> Index: https://foura.ai/llms.txt

## المشكلة

يعود استدعاء `POST /api/proxy/` مع خطأ وبدون بيانات. الرسالة قصيرة وتأتي دائماً بالصيغة نفسها:

```json
{
  "error": "Download maxTry limit reached",
  "total": 34.812,
  "request": { "...": "..." }
}
```

تُقرأ هذه الجملة بالطريقة نفسها سواء تم حظر كل مخرج، أو كان كل مخرج معطلاً، أو جلب FourA الصفحة الحقيقية في كل محاولة تقريباً وتجاهلتها قواعد `validate` الخاصة بك. تتطلب هذه الحالات الثلاث معالجات مختلفة تماماً.

## الحل: `attemptReport`

يحمل كل استدعاء Proxy استنفد محاولاته وفشل كائن `attemptReport` بجانب الخطأ، بما في ذلك الاستدعاء الذي انتهى بـ `"error": "Timeout"`. يفشل اسم المضيف الذي لا يمكن حله قبل إجراء أي محاولة، مع `status: 0` وبدون تقرير. وهو يوضح ما واجهته المحاولات فعلياً:

```json
{
  "error": "Download maxTry limit reached",
  "attemptReport": {
    "total": 25,
    "noResponse": 0,
    "defense": 0,
    "contentRejected": 25,
    "statusRejected": 0,
    "other": 0,
    "vendors": [],
    "profilesTried": ["default"],
    "summary": "25 attempt(s): 25 returned HTTP 200 with no defense present and were rejected only by your validate.data - the page was fetched, your content rule did not match it"
  },
  "total": 34.812
}
```

تظل السلسلة `error` دون تغيير عن قصد، لكي يستمر العميل الذي يطابقها في العمل. اقرأ `attemptReport.summary` للحصول على إجابة من سطر واحد، أو التعدادات عندما تريد التفرع بناءً عليها.

### الحقول

| الحقل | النوع | ما يحسبه |
|-------|------|----------------|
| `total` | integer | المحاولات المنفذة |
| `noResponse` | integer | لم تستجب عقدة الخروج مطلقًا، أو لم يستجب الموقع في الوقت المحدد |
| `defense` | integer | استجاب الموقع وجرى التعرف على مزود فحص البوتات في تلك الاستجابة |
| `contentRejected` | integer | رمز HTTP 200، بدون فحص بوتات، رُفضت فقط بواسطة `validate.data` الخاص بك |
| `statusRejected` | integer | استجاب الموقع، بدون فحص بوتات، رُفضت بواسطة `validate.status` الخاص بك |
| `other` | integer | تم الرد، ولم تندرج تحت أي مما سبق |
| `vendors` | string[] | كل مزود فحص بوتات تم التعرف عليه في أي مكان داخل المهمة |
| `profilesTried` | string[] | ملفات تعريف المتصفح التي أرسلتها المهمة، بترتيب الاستخدام الأول. `default` تعني أن الطلب خرج تمامًا كما كتبته. |
| `summary` | string | جملة واحدة تم إنشاؤها من التعدادات. آمنة للتسجيل أو العرض للمستخدم. |

## قراءتها

### `contentRejected` مرتفع

وصلت الصفحات. قاعدة `validate.data` الخاصة بك لم تطابقها.

هذه هي الحالة التي يمكنك إصلاحها بنفسك، وهي الحالة التي تخفيها جميع الإشارات الأخرى: تبدو الطلبات كإخفاقات في كل المقاييس، بينما كانت FourA تقدم محتوى حقيقيًا طوال الوقت. اجلب الصفحة مرة واحدة عبر `POST /api/single/` بدون أي `validate` على الإطلاق، وانظر إلى ما يتم إرجاعه فعليًا، وأعد كتابة القاعدة بناءً عليه.

السبب الشائع هو تطبيق قاعدة واحدة على مجموعة صفحات ليست متطابقة. فالمحدد الموجود في صفحات المقالات وغير الموجود في صفحات الفيديو يفشل في كل مرة يقع فيها على صفحة فيديو، بشكل دائم، وبالتكلفة الكاملة.

### `statusRejected` مرتفع

استجاب الموقع وقضت قاعدة `validate.status` الخاصة بك بالرفض. إذا كانت هذه الحالات 401 أو 403 أو 429 أو 503، فإن الموقع يرفض العميل بدلاً من إعلامه بعدم وجود الصفحة. جرب:

- ملف تعريف متصفح آخر (`browser` أو `os` أو `version` في كائن `request` الداخلي)
- `exitCountries` إذا كان المحتوى مقيدًا جغرافيًا
- `POST /api/browser/` إذا كان الرفض يتطلب JavaScript لتجاوزه

### `defense` مرتفع

تم التعرف على فحص بوتات في الاستجابات، ويحدد `vendors` أي منها. راجع [Site checks](https://foura.ai/docs/api/site-checks) لمعرفة ما تتجاوزه FourA حاليًا وما تكتفي بالإبلاغ عنه فقط. إذا لم يكن المزود من بين المزودين الذين يتم تجاوزهم على هذا الـ endpoint، فانقل الاستدعاء إلى `POST /api/browser/` أو `POST /api/auto/`.

### `noResponse` مرتفع

لم تستجب عقد الخروج على الإطلاق، لذا لم يتم معرفة أي شيء عن الهدف. ارفع قيمة `maxTries`، وارفع قيمة `timeout_ms`، وتحقق من إمكانية حل عنوان URL عبر شبكة الإنترنت العامة.

### `other` مرتفع

استجاب الموقع برمز حالة، ولم يتم التعرف على أي فحص بوتات، وفشلت المحاولة لسبب آخر، مثل قاعدة `validate.headers`. يُحسب الهدف الأبطأ من قيمة `timeout_ms` الخاصة بك ضمن `noResponse`.

## تدوير ملف تعريف المتصفح (Browser Profile Rotation)

عندما يرفض موقع ما المتصفح الذي أرسلته FourA، يتوقف Proxy عن الإصرار عليه ويجرب عائلة أخرى من [public profile catalogue](https://foura.ai/docs/api/endpoints). لا يكلف ذلك أي محاولة إضافية: يغير التدوير ما يرسله retry، ولا يحدد أبدا ما إذا كان سيحدث.

يتذكر Proxy أيضا، لكل موقع، العائلة التي نجحت هناك مؤخرا بعد أن رفض الموقع الإعداد الافتراضي. يمكن لـ request لاحق إلى ذلك الموقع أن يبدأ بتلك العائلة من محاولته الأولى، وتنتقل FourA إلى العائلة التالية بمجرد أن يبدأ الموقع في رفض تلك أيضا. يتم تذكر متصفح الهاتف فقط للموقع الذي يستجيب بـ JSON.

`profilesTried` هي الطريقة التي ترى بها حدوث ذلك. إدخال واحد يعني أن كل محاولة أرسلت نفس المتصفح: `default` هو الـ request كما هو مكتوب، و catalogue id هو العائلة التي تعلمتها FourA بالفعل لذلك الموقع. وجود عدة إدخالات يعني أن التدوير قد تم ورفض الموقع كل منها، وهي حالة مختلفة عن عدم التدوير على الإطلاق.

في response الـ Proxy **الناجحة**، يظهر حقل `profile` فقط عندما يختار التدوير متصفحا لم تطلبه:

```json
{
  "status": 200,
  "data": "<!doctype html>...",
  "proxy": "A1B2C3",
  "profile": "...",
  "total": 4.108
}
```

القيمة هي معرف كتالوج من `GET /api/profiles`. الغياب يعني أن الطلب قد أُرسل تمامًا كما كُتب. الوجود يعني أن المتصفح الذي نجح لم يكن هو المتصفح الذي أدخلته، لذا مرر هذا المعرف كـ `profile` في الاستدعاءات اللاحقة بدلًا من إعادة إرسال المتصفح الذي فشل. تقوم لوحة تحكم [Playground](https://foura.ai/docs/dashboard/playground) بذلك نيابة عنك عبر **Carry**.

لا يتم أبدًا تجاوز أي تعيين صريح لـ `profile` أو `browser` أو `os` أو `version` في طلبك. ولا ينطبق التجاوز أيضًا على طلب يحمل ترويسة `User-Agent` أو `Cookie` الخاصة بك، نظرًا لأن التصريح (clearance) مرتبط بالتوقيع الذي حصل عليه.

## قراءتها برمجيا

```python
import requests

API = "https://eu.api.foura.ai"
H = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}

r = requests.post(f"{API}/api/proxy/", headers=H, json={
    "maxTries": 5,
    "request": {
        "method": "GET",
        "url": "https://example.com/product/42",
        "validate": {"data": {"accept": ["Add to cart"]}},
    },
}).json()

if "error" in r:
    rep = r.get("attemptReport", {})
    print(rep.get("summary", r["error"]))

    if rep.get("contentRejected", 0) > rep.get("total", 0) / 2:
        # The pages arrived. The validate rule is what threw them away.
        raise SystemExit("validate.data did not match the real page")
    if rep.get("defense", 0):
        print("bot check met:", ", ".join(rep.get("vendors", [])))
```

## ذات صلة

- [API Endpoints](https://foura.ai/docs/api/endpoints): مرجع كامل لطلبات واستجابات Proxy
- [Site checks](https://foura.ai/docs/api/site-checks): المزودون، و`defense`، وإعادة تشغيل التصريح
- [Request Outcomes](https://foura.ai/docs/api/outcomes): كيفية تصنيف الاستجابة المرفوضة واحتساب تكلفتها
- [Common Issues](https://foura.ai/docs/troubleshooting/common-issues): مشكلات أخرى وحلولها
- [Choosing the Right Endpoint](https://foura.ai/docs/guides/choosing-task-type): متى يكون Proxy هو الأداة غير المناسبة
