# Searlo API Documentation (LLM-optimized) # https://searlo.tech/docs ## Available Formats - Full Markdown: https://searlo.tech/docs/full.md - LLM summary: https://searlo.tech/docs/llms.txt - Per-section Markdown: https://searlo.tech/docs/[section].md Available sections: introduction, quick-start, authentication, search-web, custom-search-json-api, search-images, search-news, search-videos, search-site, search-advanced, search-shopping, local-search, scholar-patents, search-simple, search-suggestions, search-batch, full-serp, serp-html, rankings, ai-answers, web-data, async-tasks, search-analytics, email-verify, account, rate-limiting, errors, mcp-server, changelog ## Quick Reference Base URL: https://api.searlo.tech/api/v1 Auth: x-api-key header with sk_... key Dashboard: https://dashboard.searlo.tech ## Endpoints GET /search — Web search, alias of /search/web (1 credit) Params: q (required), limit (1-10), page, gl, hl GET /search/web — Web search (1 credit) Params: q (required), limit (1-10), page, safe (active|off), lr, gl, hl, dateRestrict (d7, w2, m1, y1: results from that window; works with gl and hl; not with search operators in q), cache (false = search now) A page starting past result 101 is 400 PAGE_OUT_OF_RANGE with maxPage; q with operators plus dateRestrict is 400 DATE_FILTER_UNAVAILABLE. Neither is charged GET /search/images — Image search (1 credit) Params: q (required), limit (1-10), page (about 200 images per query: last page 21 at limit 10), size|imgSize (icon, small, medium, large, xlarge, xxlarge, huge), imgType (photo, face, clipart, lineart, stock, animated), imgColorType (color, gray, mono, trans), imgDominantColor (black, blue, brown, gray, green, orange, pink, purple, red, teal, white, yellow), gl, hl, cache Response: images[{position,title,imageUrl,width,height,thumbnailUrl,thumbnailWidth,thumbnailHeight,link,sourceUrl (the page),source,domain,format,imageId}] GET /search/news — News search (1 credit) Params: q (required), limit (1-10), page, gl, hl, dateRestrict (d7, w2, m1, y1), cache GET /search/videos — Video search (1 credit) Params: q (required), limit (1-10), page, safe, gl, hl GET /search/site — Site-restricted search (1 credit) Params: q (required), site (required), limit (1-10), page GET/POST /search/advanced — Advanced/filtered search (1 credit) Params: query|q (required), limit (1-10), dateRange|timeRange (day|week|month|year) or dateRestrict (d7, w2, m1, y1), fileType, exactTerms, excludeTerms, site|siteSearch, gl, hl A date cannot be combined with site, fileType or operators in q: 400 DATE_FILTER_UNAVAILABLE (not charged). exactTerms and excludeTerms work with a date GET /search/shopping — Shopping search (1 credit) Params: q (required), limit (1-55, default 55), gl, hl GET /search/simple — Legacy simple web search (1 credit) Params: q (required), limit (1-10) GET /search/suggestions — Autocomplete (0.5 credits) Params: q (required), limit (1-10), hl. Suggestions are in data.suggestions (GET /search/trending is not available: it returns no trending data) POST /search/batch — Batch search (1 credit per query, max 10) Body: queries (string[], 1-10 items) GET /search/maps — Google Maps local results (1 credit) Params: q (required), limit (1-20, default 20), page (1-100), gl, hl, ll, lat, lng, zoom, cache (false = look up now) Place fields include businessStatus (OPERATIONAL, CLOSED_TEMPORARILY, CLOSED_PERMANENTLY or null), openNow (true, false or null) and openState (in the language of hl). With no ll, lat or lng, gl sets the area searched (51 countries). lite: true is not cached: retry for the full record GET /search/places — Businesses for a query in a named place (1 credit) Params: q (required), location, limit (1-20, default 20), page, gl, hl, ll, lat, lng, cache GET /search/reviews — Reviews for one place (1 credit) Params: one of placeId (ChIJ...), featureId (0x...:0x...), cid (decimal) or q; limit (1-50, default 10), gl, hl Returns the first page Google serves (about eight reviews, in any language) with hasMore; 503 REVIEWS_WITHHELD when Google sent the place without its reviews (retryable, not charged) GET /search/place-details — One place in full: attributes, menu, hours (1 credit) Params: one of placeId (ChIJ...), featureId (0x...:0x...), cid (decimal) or q; gl, hl GET /search/scholar — Google Scholar (1 credit) Params: q, cluster or cites (one required), limit (1-20, default 10), page, hl, yearFrom, yearTo, sortByDate, includePatents, includeCitations GET /search/patents — Google Patents (1 credit) Params: q (required), limit (1-100, default 10), page, sort (new|old), country, language, status (GRANT|APPLICATION), type (PATENT|DESIGN), inventor, assignee, before, after GET /serp — Full Google SERP, alias /search/serp (3 credits per page; from 2026-11-01, +5 per request when the AI Overview had to be completed by rendering the page, shown as aioverview.rendered: true) Params: q (required, max 400), gl (default us), hl (default en), location (a country by name or code, applied as gl) or uule (a country's token), device (desktop; mobile|tablet are accepted and return the desktop layout), page (1-100), pages (1-10), num (1-100), tbs, safe (active|off, or true|false), aioverview (default true), googleGoto, googleGotoOrganic, cache, rawHtml (+1 credit: adds rawHtml, the page's HTML) Location: countries only. A city or state location, or any non-country uule, returns 400 code CITY_LOCATION_UNAVAILABLE (not charged): Google no longer localizes results by uule. Same rule on /serp/batch, /serp/features, /search/news/serp, /serp/html, /rankings and async serp tasks Response: organic[] (url, not link), videos, ads, peopleAlsoAsk, relatedSearches, knowledgeGraph, aioverview (complete: true when read in full; pending: true when Google loads it after the page; rendered: true when it was completed from the rendered page; sources resolved), aiModeAvailable, pagesFetched, gotoResolved, fetchedAt, source, cached GET /serp/html — Google's results page as HTML: as Google sent it (2 credits per page), or rendered with the AI Overview opened out, js=true (8 credits per page). Never cached Params: q (required, max 400), gl (default us), hl (default en), page (1-10), tbs, safe (active|off), device (desktop|ios; ios = the iPhone Safari layout), js (default false), expandAio (default true; with js: Show more and Show all expanded), format (json|raw), location (a country, applied as gl; a city or state returns 400 CITY_LOCATION_UNAVAILABLE) Errors (never charged): 400 VALIDATION_ERROR | CITY_LOCATION_UNAVAILABLE | UNKNOWN_LOCATION, 422 QUERY_NOT_SERVED (search operators, e-mail lookups, long OR chains), 429 BUSY (Retry-After), 503 UPSTREAM_UNAVAILABLE (retryable). Latency p50 ~3 s raw, ~9 s rendered; client timeouts 30 s raw, 90 s rendered Response: html, url, empty, rendered, bytes, fetchedAt; with js=true also aio {present, expanded, sourcesOpened, showAll, sources, sourcesVisible} and aiOverview (desktop). format=raw returns the page as text/html with X-Searlo-Url, X-Searlo-Empty, X-Searlo-Rendered, X-Searlo-Aio headers POST /serp/batch — Full SERP for up to 20 keywords (3 credits per distinct keyword per page delivered, +5 per keyword whose AI Overview was rendered from 2026-11-01; a failed keyword in a 200 batch costs nothing) Body: keywords (1-20), gl, hl, location (a country) or uule, device, pages, num, tbs, safe, aioverview (default false), googleGoto, cache GET /serp/features — SERP features present for a query (3 credits; never renders) Params: q (required), gl, hl, location (a country) or uule, device, safe, cache GET /search/news/serp — Google News results page, fetched live and parsed, ~1 s per page (2 credits per page) Params: q (required), gl, hl, location (a country) or uule, page, pages, tbs, googleGoto, cache Response: news[{position,title,url,redirectUrl,resolved,source,snippet,date,thumbnail,page}], hasNextPage, pagesFetched, gotoResolved POST /rankings/check — Where a domain ranks for a keyword (3 credits per 10 results of depth; default depth 100 = 30) Body: keyword, domain (required), depth (10-100, default 100), gl, hl, device (desktop|mobile), location (a country by name, code or uule, applied as gl; a city or state returns 400 CITY_LOCATION_UNAVAILABLE), cache POST /rankings/batch — Rank checks for up to 20 keywords, one domain (same price per distinct keyword) GET /rankings/history — Stored rank checks (free) Params: domain (required), keyword, gl, device, from, to, limit (1-1000, default 100) GET /search/ai/{engine} — AI answer with citations: chatgpt (8 credits), copilot (8), gemini (4). perplexity is paused; aimode and grok are switched off (403 FEATURE_NOT_AVAILABLE, not charged) Params: q (required, max 500), gl, hl, cache (default true; false forces a fresh, billed run), mode, model, html (true: also an HTML snapshot of the answer page; same credits; never cached). Cached answers are billed in full Response: answer, answerMarkdown, citations[{index,url,title,domain}], sources, citationPills (Copilot), related, model, threadUrl, complete, cached; with html=true also html and pageUrl POST /scrape — One URL as markdown, text, html, links, images, headings, tables, json_ld (1 credit; 2 when maxAge or cache:false forces a live fetch; from 2026-11-01, +4 when the page needed a browser, via: browser) POST /scrape/batch — Up to 1000 URLs as one job (1 credit per page fetched; 5 from 2026-11-01 for a page that needed a browser) POST /map — Every URL a site publishes (1 credit; same live-fetch rule as /scrape) POST /crawl — Crawl a site as a job (1 credit per page; 5 from 2026-11-01 for a page that needed a browser); GET /crawl/{jobId}, GET /crawl/{jobId}/results and DELETE /crawl/{jobId} are free POST /extract — URLs plus a field schema in, records out (1 credit per page fetched, 5 from 2026-11-01 for a page that had to be rendered; failed rows are free). URLs are fetched in parallel inside one time budget Failed rows carry errorCode (TARGET_REFUSED, TARGET_NOT_ALLOWED, TARGET_UNREACHABLE, INVALID_REQUEST, SCRAPE_FAILED, TIMEOUT, NOT_FETCHED) and retryable; partial: true when the budget ran out; llmSkipped: "time budget" when the model was not asked scrape, map, crawl, scrape/batch and extract accept internationalised domain names (https://www.löschwagen.com); a malformed URL or a control character is 400 POST /search-and-scrape — Web search, then scrape the result pages (1 + 1 per page scraped; 5 per page from 2026-11-01 for a page that had to be rendered) POST /async/task — Queue a task. Body: endpoint (required), request, webhook {url, secret}, priority (1-100), idempotencyKey Reply 202: { success, duplicate, task: { taskId, status, creditsHeld, ... } }. Credits held at enqueue, refunded if the task fails POST /async/task/batch — Up to 500 tasks in one request GET /async/task/{taskId} — Task status and result (free) GET /async/status — Queue counts (free) GET /credits/balance — Credits available to the account, for an API key or a dashboard login (free): { success, credits: { available, reserved?, expiresAt?, expiringCredits? } } GET /search/analytics — Your search analytics (free) Params: startDate, endDate, searchType POST /email-verifier/verify — Verify email deliverability (5 credits) Body: email (required). status: valid|invalid|accept_all|unknown|error GET /email-verifier/history — Verification history (free) Params: page, limit (1-100, default 20) ## MCP Server URL: https://api.searlo.tech/api/v1/mcp Transport: Streamable HTTP Auth: X-API-Key header Tools: web_search (1 credit), check_balance (free), get_usage_stats (free), get_search_history (free), get_search_stats (free), get_transaction_history (free), list_api_keys (free) web_search params: query (required), num (1-10), page, gl, lr, safe (off|medium|high), format (toon|json|enhanced) ## Authentication Example ```bash curl "https://api.searlo.tech/api/v1/search/web?q=hello+world" \ -H "x-api-key: sk_your_api_key" ``` ## Error Codes Errors answer JSON { success: false, code, message, retryable?, retryAfterSec? }. Branch on code, not message. On the 4xx marked + the name is in errorCode instead: read code, then errorCode. No error is ever charged, and an answer with no results is free (a failed row inside a 200 POST /rankings/batch is the one exception). 400 VALIDATION_ERROR | INVALID_JSON | INVALID_IDEMPOTENCY_KEY | CITY_LOCATION_UNAVAILABLE | UNKNOWN_LOCATION | INVALID_DOMAIN | PAGE_OUT_OF_RANGE+ | DATE_FILTER_UNAVAILABLE+ | INVALID_REQUEST+ | PLACE_NOT_FOUND+ (also 404) 401 UNAUTHORIZED — missing, invalid or expired API key 402 INSUFFICIENT_CREDITS — details {required, available, shortfall}, topUpUrl 403 FORBIDDEN (account suspended) | FEATURE_NOT_AVAILABLE (endpoint switched off, retryable: false) | API_KEY_SCOPE_FORBIDDEN (an API key on account, API-key, export, delete or payment routes; GET /user/profile stays open) 404 NOT_FOUND | 409 IDEMPOTENCY_REQUEST_IN_PROGRESS | 413 PAYLOAD_TOO_LARGE 422 QUERY_NOT_SERVED | COUNTRY_UNAVAILABLE (SERP, SERP HTML) | IDEMPOTENCY_KEY_REUSED | TARGET_REFUSED+ | TARGET_NOT_ALLOWED | TARGET_UNREACHABLE+ (web data) 429 4201 (account rate limit) | 4202 (API key rate limit) | 4203 CONCURRENCY_LIMIT (searches in flight) | AT_CAPACITY | BUSY | VERIFIER_BUSY — wait Retry-After 500 INTERNAL_ERROR 503 UPSTREAM_UNAVAILABLE | UPSTREAM_RATE_LIMITED | AT_CAPACITY | WARMING | UPSTREAM_TIMEOUT | CREDIT_SYSTEM_UNAVAILABLE | REVIEWS_WITHHELD (retryable: true, wait Retry-After) | SERVICE_UNAVAILABLE | UPSTREAM_FAILED (retryable: false) Idempotency: send X-Idempotency-Key (max 255 characters). The same request replays the stored response (Idempotent-Replayed: true, no charge); the same key with another request is 422 IDEMPOTENCY_KEY_REUSED ## Rate Limits Every account, free credits included, gets the same sliding-window limits per endpoint group: search (search, SERP, rank checks, AI answers, web data) — 600/s, 20,000/min, 400,000/hr, 1,800,000/day local (maps, places, reviews; inside the search limit) — 20/s, 48/min, 2,400/hr, 16,000/day email_verifier — 40/s, 200/min, 10,000/hr, 40,000/day mcp — 60/s, 1,200/min, 16,000/hr, 150,000/day Per API key, inside the account budget: 20,000/min and 400,000/day by default for a new key (fixed windows). Custom account and key limits on request In flight: at most 64 web, image, site, advanced and batch searches at once per account; past it 429 code 4203 CONCURRENCY_LIMIT, Retry-After 1, header X-Concurrency-Limit Headers: X-RateLimit-Limit-{Second,Minute,Hour,Day}, X-RateLimit-Remaining-{Second,Minute,Hour,Day}, X-RateLimit-Reset (Unix seconds); 429 carries Retry-After ## Pricing Free: 3,000 credits on sign-up From $3.99 (5,000 credits) to $799 (4,000,000 credits) New users receive 1-year credit validity; legacy users keep unlimited credits. One-time purchase. Pricing may change during November–December 2026. What it costs us to serve some requests changes at the turn of the year, so we may adjust prices during November and December 2026. Any change is announced in advance on the changelog and by email. Credits you have already bought keep working, and packs stay valid for 12 months from purchase. From 2026-11-01: a full-SERP page whose AI Overview had to be completed by rendering the page costs 8 credits instead of 3 (aioverview.rendered: true); a scraped, crawled, extracted or fetched page that needed a browser costs 5 instead of 1 (via: browser). See the changelog. ## Links - Docs: https://searlo.tech/docs - API Reference: https://searlo.tech/api-reference - OpenAPI spec: https://searlo.tech/openapi.yaml - Dashboard: https://dashboard.searlo.tech - MCP Setup: https://searlo.tech/mcp - Homepage: https://searlo.tech # For full documentation with code examples, use: https://searlo.tech/docs/full.md