مسیرهای قدیمی
مسیرهای قدیمی /api/* هنوز کار میکنند، منسوخ نشدهاند، محدودیت نرخ ندارند و کوکی نشست داشبورد را هم میپذیرند.
اینها برای کلاینتهایی هستند که همین حالا نوشته شدهاند. برای اتصال تازه از API منابع /api/v1/operator/* استفاده کنید.
نگاشت مسیرها
| مسیر قدیمی | معادل نسخهدار |
|---|---|
POST /api/query | POST /api/v1/operator/query |
GET /api/results/{task_id}/serpapi|markdown|raw | GET /api/v1/operator/results/{task_id}/serpapi|markdown|raw |
GET /api/selector-health | GET /api/v1/operator/selector-health |
GET /api/results هیچ معادلی در v1 ندارد. چون
/api/v1/operator/results کاملتر است و این دو یک پرسوجو نیستند. جدول
مقایسه در پایین همین صفحه آمده.دو نام متفاوت برای یک کار
POST /api/query (قدیمی) و POST /api/v1/operator/query (معادل) هر دو همان رفتار قدیمی را دارند — یعنی همان دو تفاوت پنهان. POST /api/v1/operator/queries (با s جمع) جزو API منابع است و رفتار متفاوتی دارد.
/api/query قدیمی | /queries در API منابع | |
|---|---|---|
| هدف میسازد؟ | اگر cadence_hours > 0، بله و بیسروصدا | هرگز |
فیلد deduped | ندارد | دارد |
| از کجا بفهمید تکراری بود | enqueued: false بهعلاوهٔ reason | deduped: true |
ثبت در مسیر قدیمی
POST /api/query — مثل بقیهٔ مسیرها به scope نیاز دارد.
city اختیاری است (null یا "" یعنی کل ایران). محدود شدن pages و expand_answers مثل
POST /queries است.
نمونهٔ درخواست:
curl -s -X POST -H "X-API-Key: $KEY" -H 'Content-Type: application/json' \
-d '{"domain":"example.ir","keyword":"shoes"}' \
https://serp.rasaad.ir/api/query
نمونهٔ پاسخ:
{"ok": true, "task_id": "…", "keyword": "…", "domain": "…", "city": "",
"location": "iran", "recurring": false, "pages": 1, "expand_answers": 0,
"enqueued": true, "reason": "created"}
مقادیر reason: created، already_active، recently_done.
تفاوت اول: پاسخ فیلد deduped ندارد. نشانهٔ معادل، enqueued: false بهعلاوهٔ
reason برابر با already_active یا recently_done است.
cadence_hours > 0 بیسروصدا یک هدف تکرارشونده میسازد — یعنی یک upsert پنهان داخل درخواست ثبت. اگر یک خزش یکباره میخواستید و cadence_hours را از یک تنظیم پیشفرض یا یک متغیر محیطی گرفتهاید، ناخواسته یک زمانبندی دائمی ساختهاید. POST /queriesهرگز این کار را نمیکند.خواندن نتیجه در مسیر قدیمی
GET /api/results — به ?task_id= یا ?domain=&keyword= (با city اختیاری) نیاز دارد.
نمونهٔ درخواست:
curl -s -H "X-API-Key: $KEY" \
"https://serp.rasaad.ir/api/results?domain=example.ir&keyword=shoes"
نمونهٔ پاسخ:
{"ok": true, "task_id": "…", "result": { … }}
یا برای قالب تاریخچهای:
{"ok": true, "domain": "…", "keyword": "…", "city": "",
"count": 1, "results": [ { … }, … ]}
قالب تاریخچهای، تاریخچهٔ رتبه است و اسناد را جدیدترین اول، کامل و بدون حلقهٔ صفحهبندی برمیگرداند.
مقایسه با API منابع
GET /api/results | /api/v1/operator/results | |
|---|---|---|
| جستوجو با | task_id، یا domain+keyword(+city) | target_id، یا domain/keyword/city |
| فیلترها | هیچ | target_id، domain، keyword، city، since، until |
| صفحهبندی | فقط limit (حداکثر ۱۰۰) | limit + کرسر امضاشده، با total |
| کلید بدنه | results | rows |
| احراز هویت | کلید یا کوکی داشبورد | فقط کلید API |
domain+keyword روی هر دو کار میکند و همان ردیفها را برمیگرداند. یعنی
کلاینتی که فقط همین فرم را استفاده کرده بدون تغییر میتواند مهاجرت کند. فقط کلید بدنه
از results به rows عوض میشود و total اضافه میشود.کوکی نشست داشبورد
مسیرهای قدیمی کلید API یا کوکی نشست داشبورد را میپذیرند. API منابع فقط کلید API.
محدودیت نرخ ندارند
مسیرهای قدیمی محدودیت نرخ ندارند و هدرهای X-RateLimit-* را نمیفرستند.
X-RateLimit-Remaining را میخواند باید نبودن هدر را مدیریت کند — نه اینکه KeyError بدهد و نه اینکه عدد ساختگی بگذارد.سلامت استخراج
GET /selector-health — نیازمند results:read.
گزارش سلامت استخراج: میگوید نتایج اخیر هنوز درست خوانده میشوند یا نه. پارامتر ?limit=
(از ۱۰ تا ۱۰۰۰، پیشفرض ۲۰۰) سقف میگذارد چند اجرای اخیر بررسی شوند.
نمونهٔ درخواست:
curl -s -H "X-API-Key: $KEY" \
https://serp.rasaad.ir/api/selector-health?limit=200
نمونهٔ پاسخ:
{
"ok": true,
"verdict": {
"status": "ok",
"runs_considered": 42, "runs_total": 51, "blocked": 9,
"rotated": [
{"selector": "display_domain", "runs_seen": 42, "runs_hit": 36,
"hit_rate": 0.857, "distinct_bots": 6,
"last_hit": "2026-10-02T08:14:02Z", "runs_since_hit": 6,
"selectors": ["span.VuuXrf"]}
],
"partial": [], "stale_versions": {"0.5.11": ["display_domain"]},
"healthy": ["title_h3", "breadcrumb", "root"]
}
}
status یکی از ok، partial یا rotated است و تعیین میکند چه کنید:
| مقدار | یعنی چه | کار کنید |
|---|---|---|
ok | همهچیز سالم است | کاری لازم نیست |
partial | بعضی فیلدها ناقصاند | احتیاط کنید و به پشتیبانی خبر دهید |
rotated | بخشی از فیلدها دیگر قابل اعتماد نیست | به آن فیلدها اعتماد نکنید و گزارش دهید |
اجراهای بلاکشده و خطاخورده در runs_considered شمرده نمیشوند، چون صفحهٔ کپچا نتیجهای
برای سنجش ندارد. برای همین runs_considered میتواند کمتر از runs_total باشد.
status چیزی غیر از ok بود، خودتان نمیتوانید درستش کنید. به پشتیبانی خبر دهید و صبر کنید. در
نتایج توضیح داده شده کدام فیلدهای سند به آن وابستهاند.چکلیست مهاجرت
POST /api/queryرا باPOST /queriesجایگزین کنید.enqueuedرا بهdedupedتبدیل کنید.resultsرا بهrowsتغییر دهید.- کوکی نشست را کنار بگذارید و فقط کلید API بفرستید.
- رفتار
429را اضافه کنید و هدرهایX-RateLimit-*را بخوانید.