Turn a Google results page into structured JSON.
A live Google SERP is a moving collage — organic links, ads, a featured snippet, People-Also-Ask, a map pack, news and a knowledge panel, each rendered differently and reshuffled weekly. cloro fetches the page and parses every block into one predictable, typed record you can store and diff.
# parse a live Google SERP into normalized JSON curl https://api.cloro.cloud/v1/serp/google \ -H "Authorization: Bearer $CLORO_KEY" \ -d '{ "q": "wireless earbuds", "location": "Austin, Texas", "device": "mobile", "page": 1 }' # → response { "query": "wireless earbuds", "organic": [ { "rank": 1, "domain": "rtings.com", "title": "Best Earbuds 2026" } ], "ads": [ { "slot": "top", "domain": "sony.com" } ], "featured_snippet": { "type": "paragraph" }, "people_also_ask": [ "Are earbuds bad for ears?" ], "local_pack": 3, "news": 2, "knowledge_panel": "present", "billed": "success" }
Every block on the page, named and typed.
Google doesn't ship a clean data model — it ships HTML that changes without notice. cloro reads the whole results page and returns each element as its own array of records, so you never scrape a div again.
Organic & ads, ranked
True positions for both paid and unpaid listings, with title, URL, display domain, sitelinks and the ad slot — top, bottom or shopping — kept distinct from organic ranks.
Snippets & PAA
Featured snippets typed as paragraph, list or table, plus the full People-Also-Ask tree with each question, its answer and the source that Google attributes it to.
Maps, news & panels
Local map packs with place, rating and address; news carousels with source and timestamp; and knowledge panels flattened into clean key-value attributes.
One schema that survives Google's redesigns.
Layouts move, class names churn, blocks get renamed. Our parser maps whatever Google renders back onto stable field names — so the record you stored last quarter still lines up with the one you pull today.
- Stable keys for every block, so day-over-day diffs just work
- Ad, organic and snippet ranks kept in separate namespaces
- Empty blocks returned as typed empties, never missing keys
- Absolute URLs, decoded titles and de-duplicated results
# same keys, whatever Google renders today { "organic": "[]", "ads": "[]", "featured_snippet": "null", "people_also_ask": "[]", "local_pack": "[]", "news": "[]", "knowledge_panel": "null", "related_searches": "[]", "pagination": { "page": 1 } }
Three steps to a parsed SERP
Set query & targeting
Pass q plus the location, gl/hl and device you want. cloro renders the SERP the way a real user in that market and on that screen would see it.
Page through results
Ask for page 1, 2, 3… and get consistent ranks across the set. Pagination metadata tells you how deep the results run so you can stop cleanly.
Get normalized JSON
Each block arrives as its own typed array, deduplicated and ready to diff. Only successful, non-empty responses are billed — retries and blocks are on us.
SERP feature coverage
Track which page features you win across a keyword set — the snippet, the map pack, a PAA answer — not just your blue-link rank.
From rank tables to full SERP intelligence
- SEO platforms — power rank tables and feature tracking without maintaining scrapers
- Ad teams — watch competitor ad copy and slot occupancy on high-value queries
- Market research — pull local packs and news blocks across cities and countries
- Data pipelines — feed normalized SERP records straight into your warehouse
SERP API, answered
Which SERP elements does cloro parse?
Organic results, ads, the featured snippet, People-Also-Ask, local map packs, news carousels, knowledge panels and related searches — each returned as its own typed field in one response.
Can I target a location and device?
Yes. Every request accepts location, country and language parameters plus a device flag, so you get the exact SERP a desktop or mobile user in that market would see.
How does pagination work?
Pass a page number and cloro returns that slice with consistent ranks and pagination metadata, so you can walk results in order and know when to stop.
What happens when a block isn't present?
Absent blocks come back as typed empties — an empty array or null — never as missing keys. Your parser sees the same shape on every call.
How am I billed?
Per successful call. Blocked, failed or empty responses aren't charged, and your live usage counter reflects only the parsed SERPs you actually received.
Stop scraping HTML. Start reading SERPs as data.
Grab a key, send one query, and get the whole Google results page back as normalized JSON in minutes.