POST /v1/search
Firecrawl-compatible web search. Returns SERP results with optional full-page markdown and an optional LLM-generated answer.
Provider cascade: DataForSEO SERP API → DuckDuckGo HTML → Bing HTML. The first provider that returns results is used; the source field in the response tells you which one fired.
When include_answer is true, the top-5 results are summarised by the LLM router (DeepSeek/Claude/Llama by tier). If the LLM is unavailable or no keys are configured the answer field is simply omitted, the search result is never failed because of the answer step.
Request
POST /v1/search
Content-Type: application/json
x-api-key: YOUR_KEYBody
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes | Search query string. | |
limit | number | No | 10 | Max results. Clamped by plan (free max 20). |
scrapeResults | boolean | No | false | Fully scrape each result URL to markdown. Does not add per-URL scrape credits today � only the search unit charge (2 per 10 results). Full page content is included when available. |
country | string | No | "us" | Two-letter country code for geo-localised results (e.g. "mx", "br"). |
include_answer | boolean | No | false | Generate an LLM answer citing the top results (Tavily/Exa pattern). Gracefully omitted if llm-router is unavailable. |
includeDomains | string[] | No | Restrict results to these domains. Translated to site: operators. Up to 20, normalized to bare hosts. | |
excludeDomains | string[] | No | Exclude these domains. Translated to -site: operators. Up to 20. | |
categories | string | string[] | No | Content categories, translated to operators: github → site:github.com, research → arxiv/scholar, pdf → filetype:pdf. | |
sources | string | string[] | No | Accepted and echoed back; only web is currently honored (news/images degrade to web). | |
tbs | string | No | Google time filter, e.g. qdr:d (past day), qdr:w, qdr:m, qdr:y. |
Operators you type in query (e.g. site:, filetype:) pass through verbatim. The response
echoes what actually ran in a search object (effectiveQuery plus the applied
categories/sources/tbs/includeDomains/excludeDomains).
Example request, basic search
curl -X POST https://api.superscraper.dev/v1/search \
-H "x-api-key: ss_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"query": "best plumbers Austin TX",
"limit": 5,
"country": "us"
}'Example request, with answer
curl -X POST https://api.superscraper.dev/v1/search \
-H "x-api-key: ss_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"query": "how to get a contractor license in Texas",
"limit": 10,
"include_answer": true
}'Response
HTTP 200 when a backend completed (even if zero hits).
HTTP 503 search_unavailable when every backend failed — never invents a vendor name.
Body
| Field | Type | Description |
|---|---|---|
query | string | The original query (operators applied are in search.effectiveQuery) |
results | array | Search result items (see below) |
source | string | null | Backend that produced rows or completed empty: "dataforseo", "duckduckgo", "bing". null only when no backend completed |
total | number | Number of results returned |
error | string | undefined | On empty success: "no_results". Total failure is HTTP 503, not this field |
answer | string | undefined | LLM-generated answer (only present when include_answer: true and results exist) |
search | object | What actually ran: effectiveQuery plus the applied categories/sources/tbs/includeDomains/excludeDomains |
| Credits | headers | Successful hits bill 2 credits per 10 results (X-Credits-Consumed / X-Credits-Remaining) |
Result item
| Field | Type | Description |
|---|---|---|
url | string | Result URL |
title | string | Page title |
snippet | string | Short text snippet from the SERP |
position | number | Rank position (1-based) |
markdown | string | null | Full page markdown, only populated when scrapeResults: true |
Example response
{
"query": "best plumbers Austin TX",
"results": [
{
"url": "https://www.yelp.com/search?find_desc=plumbers&find_loc=Austin%2C+TX",
"title": "Best Plumbers in Austin, TX - Yelp",
"snippet": "Top 10 Best Plumbers in Austin, TX, Acme Plumbing, Longhorn Pipes & More...",
"position": 1,
"markdown": null
},
{
"url": "https://www.angi.com/companylist/us/tx/austin/plumbers.htm",
"title": "Top Rated Plumbers in Austin TX | Angi",
"snippet": "Hire a local Austin plumber, read verified reviews and get free quotes.",
"position": 2,
"markdown": null
}
],
"source": "duckduckgo",
"total": 5
}Example response, with answer
{
"query": "how to get a contractor license in Texas",
"results": [ ... ],
"source": "duckduckgo",
"total": 10,
"answer": "In Texas, contractor licensing requirements vary by trade. Electricians and plumbers must be licensed by TDLR [1]. General contractors are regulated at the city or county level rather than the state level [2]. To apply, visit the TDLR website, complete the appropriate application, and pass a trade exam [1]."
}Errors
| Status | Error | Cause |
|---|---|---|
| 400 | `query` is required | query field missing or empty |
| 400 | Invalid JSON body | Malformed request body |
| 401 | API key required | Missing x-api-key header |
| 401 | Invalid or revoked API key. | Key not found or deactivated |
| 429 | Rate limit exceeded | Too many requests in the sliding window |
Notes
scrapeResults: truefires one/v1/scrapecall per result URL and counts toward your scrape quota.- The
answerfield cites sources by[number]referencing the result array positions. - All requests are logged to
usage_logs(endpoint/v1/search) regardless of whether results were found.