Research · SERP API — Fetch & Parse Organic Results, AI Overviews, PAA, Featured Snippets & Reddit Blocks
Fetch the full SERP for any query — organic results, AI Overviews, featured snippets, People Also Ask, Reddit blocks, video carousels, local pack — parsed, persisted, and diffable over time.
Fetch the full SERP for any query — organic results, AI Overviews, featured snippet, People Also Ask, Reddit blocks, video carousels, local pack — parsed and ready to use.
SERPs are persisted; every fetch creates a SearchResult record you can read back later. Useful for diff-over-time analysis (see research · serp gap for the cliff-detection sibling).
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/research/serp | Fetch and parse a SERP |
| GET | /v1/research/serp | List recent SERPs |
| GET | /v1/research/serp/{id} | Get a SERP by ID |
| GET | /v1/research/serp/diff | Diff two SERPs for the same query over time |
POST /v1/research/serp
Request
POST /v1/research/serp HTTP/1.1
Host: api.citationbench.com
Authorization: Bearer sk_live_***
X-Workspace-Id: ws_acme
Content-Type: application/json
Idempotency-Key: 7f3a1b18-7d8b-4f3e-9c4b-2c1a3e0a9b8f
{
"query": "best project management software for engineering teams",
"device": "desktop",
"location": "us",
"language": "en",
"topN": 50,
"include": ["organic", "ai_overviews", "paa", "featured_snippet", "reddit"],
"freshness": "now"
}Parameters
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
query | string | yes | — | The search query |
device | "desktop" | "mobile" | no | "desktop" | — |
location | ISO-3166 | no | workspace default | — |
language | ISO-639-1 | no | workspace default | — |
topN | number | no | 50 | Max organic results returned |
include | string[] | no | all parseable blocks | Limit which blocks get parsed |
freshness | "now" | "cached" | no | "now" | cached returns a stored SERP if one exists within cacheMaxAgeMinutes; otherwise refetches |
cacheMaxAgeMinutes | number | no | 30 | — |
Response
HTTP/1.1 202 Accepted
{
"invocationId": "inv_***",
"agentId": "agt_***",
"skill": "research.serp",
"status": "RUNNING",
"estimatedCost": { "credits": 1, "durationSeconds": 5 }
}Final result
GET /v1/agent/invocations/{invocationId}:
{
"invocationId": "inv_***",
"agentId": "agt_***",
"skill": "research.serp",
"status": "SUCCEEDED",
"creditsUsed": 1,
"result": {
"serpId": "srp_***",
"query": "best project management software for engineering teams",
"device": "desktop",
"location": "us",
"language": "en",
"fetchedAt": "2026-05-24T08:15:01Z",
"organic": [
{
"rank": 1,
"url": "https://wettletter.com/best-pm-tools-engineering",
"title": "...",
"snippet": "...",
"domain": "wettletter.com",
"isOwnedDomain": false
},
{
"rank": 2,
"url": "https://engineering-blog.com/best-pm-tools",
"title": "...",
"snippet": "...",
"domain": "engineering-blog.com",
"isOwnedDomain": false
},
// ...
{
"rank": 14,
"url": "https://acme.com/engineering",
"title": "...",
"snippet": "...",
"domain": "acme.com",
"isOwnedDomain": true
}
],
"aiOverviews": {
"present": true,
"summary": "Engineering teams typically choose Linear, Jira, or specialized tools like ...",
"cited": [
{ "domain": "linear.app", "url": "https://linear.app/features" },
{
"domain": "atlassian.com",
"url": "https://atlassian.com/software/jira"
}
]
},
"featuredSnippet": null,
"paa": [
{
"question": "What is the best project management tool for software development?",
"answer": "..."
}
],
"reddit": [
{
"url": "https://reddit.com/r/projectmanagement/comments/abc/...",
"title": "Best PM tool for engineering teams 2026"
}
],
"videos": [],
"localPack": null
},
"raw": "Fetched SERP, parsed 50 organic results. AI Overview present with 2 cited domains ...",
"files": ["agent-workspace/serp-raw.json"]
}GET /v1/research/serp
curl -G "https://api.citationbench.com/v1/research/serp" \
-H "Authorization: Bearer sk_live_***" \
--data-urlencode "query=project management software" \
--data-urlencode "location=us" \
--data-urlencode "since=2026-05-01T00:00:00Z" \
--data-urlencode "limit=20"| Param | Notes |
|---|---|
query | Exact match |
queryContains | Substring match |
location / language / device | — |
since / until | ISO timestamps |
limit, cursor | Pagination |
Returns the same shape as the invocation result, lighter (no organic body unless ?includeOrganic=true).
GET /v1/research/serp/{id}
curl https://api.citationbench.com/v1/research/serp/srp_*** \
-H "Authorization: Bearer sk_live_***"Returns the full stored SERP.
GET /v1/research/serp/diff
curl -G https://api.citationbench.com/v1/research/serp/diff \
--data-urlencode "from=srp_old" \
--data-urlencode "to=srp_new"Returns the rank deltas, new entrants, lost entrants, AI-overview citation changes between two SERPs of the same query.
{
"fromSerpId": "srp_old",
"toSerpId": "srp_new",
"fromFetchedAt": "2026-05-17T08:15:00Z",
"toFetchedAt": "2026-05-24T08:15:00Z",
"ownedDomainDelta": { "position": +3, "previous": 17, "current": 14 },
"topDelta": [
{
"url": "https://engineering-blog.com/best-pm-tools",
"previous": 4,
"current": 2,
"delta": -2
},
{
"url": "https://wettletter.com/...",
"previous": 6,
"current": 1,
"delta": -5
}
],
"newEntrants": [{ "url": "https://newentrant.io/pm-eng", "current": 9 }],
"lostEntrants": [{ "url": "https://oldentrant.com/pm-eng", "previous": 12 }],
"aiOverviewChanges": {
"added": ["linear.app/features"],
"removed": ["clickup.com/pm"]
}
}MCP
> Fetch the SERP for "best project management software for engineering teams" in the US, mobile.Claude calls research.serp.fetch.
> Diff that SERP against last week's.Claude calls research.serp.diff.
Errors
| Status | Code | Cause |
|---|---|---|
| 400 | validation_error | Missing query |
| 503 | external_unavailable | DataForSEO down |
Cost
| Action | Credits |
|---|---|
POST /v1/research/serp (per query) | 1 |
GET endpoints | free |
GET /diff | free |
Use cases (string things together)
A. Trigger a SERP fetch before a content refresh
SERP=$(curl -sf -X POST .../v1/research/serp -d '{
"query": "engineering team capacity tracking"
}' | jq -r '.invocationId')
# Pass serpId into produce.refine so the agent has fresh SERP context
curl -X POST .../v1/produce/refine -d '{
"contentId": "cnt_***",
"refinerId": "rfn_serp-context"
}'B. Detect serp cliffs to find winnable queries
Use the sibling endpoint research.serp_gap, which builds on research.serp to detect a winnable gap.
C. Weekly SERP diff for top brand queries
Cron research.serp.fetch weekly on a list of brand queries; research.serp.diff against the prior week; alert on owned-domain drops.
D. Snapshot a SERP for record-keeping
curl -X POST .../v1/research/serp -d '{
"query": "acme.com",
"freshness": "now"
}'Persists a dated snapshot — useful when a client wants proof of state.
Related
- API: Research · serp gap analysis
- API: Research · keyword
- API: Link Building · serp outreach (consumes SERPs)
- Concept: 2D Keyword Labelling
Keyword
Run agentic keyword discovery jobs, then label every keyword on the 2D intent × relevance axes and manage your full persistent keyword library with CRUD, rank tracking, and bulk operations.
SERP gap analysis
Score whether a SERP is winnable by detecting DR, content, brand, and intent cliffs — the highest-ROI question to ask before committing content production to a keyword.