Skip to content
SpideyData

SERP guide · schema walkthrough

How to Get Google Search Results as JSON

Google: live · not GA

A field-by-field walk through the JSON you get back for a Google query, with the fields that can be null called out so your parser does not break on the first empty snippet.

Published · Updated

Two kinds of “Google JSON”

Source

Custom Search JSON API: Index behind your Programmable Search Engine

Live SERP JSON (/v1/serp/google/organic): The public results page, fetched per request

Result array

Custom Search JSON API: items[]

Live SERP JSON (/v1/serp/google/organic): organic[]

Position

Custom Search JSON API: Order in items[]

Live SERP JSON (/v1/serp/google/organic): organic[].rank

The request

JavaScript fetch with null guards
const res = await fetch("https://kieapi.com/v1/serp/google/organic", {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.KEY, "Content-Type": "application/json" },
  body: JSON.stringify({ q: "json schema validator", hl: "en" }),
});
const data = await res.json();
const rows = data.organic.map((o) => ({ pos: o.rank ?? null, url: o.url, desc: o.snippet ?? "" }));
console.log(data.organic_count, rows);

country is omitted here, so it defaults to US.

Annotated response

SerpOrganicResponse, line by line.

Response (SerpOrganicResponse)
{"engine":"google",                       // which engine answered
 "query":{"q":"json schema validator","country":"US"},  // echo of q and the country used
 "request_url":"<request_url>",           // the results page that was fetched
 "status_code":200,                       // upstream status for that fetch
 "classification":"<classification>",     // how the fetched page was classified
 "organic":[{"rank":1,"title":"…","url":"https://…","display_url":"…","snippet":null}],
 "modules":{},                            // open object; no sub-module is promised
 "organic_count":10}                      // number of rows in organic[]

Comments are for reading only; the API returns plain JSON.

Null-safety table

title

Type: string

Can be null?: no (not marked required)

Guard: if (o.title) …

url

Type: string

Can be null?: no (not marked required)

Guard: if (o.url) …

rank

Type: integer

Can be null?: yes

Guard: o.rank ?? null

display_url

Type: string

Can be null?: yes

Guard: o.display_url ?? o.url

snippet

Type: string

Can be null?: yes

Guard: o.snippet ?? ""

News and Images JSON shapes

  • /v1/serp/google/news returns news[] (rank, title, url, snippet, source, date, image_url) and news_count.
  • /v1/serp/google/images returns images[] (rank, title, url, source_url, encoded_url, subtitle, alt, domain) and images_count.
  • Both add vertical (news or images) next to engine, query, request_url, status_code and classification.

Launch status for this page

Check engine availability before choosing an endpoint. Google also supports News, Images and asynchronous tasks.

  • GoogleLiveGoogle is callable today with a Bearer API key.

SERP searches are charged per successful search at a display rate of 2 Credits per search; failed searches are not charged. Polling task status is free. The current rate is on Pricing.

Frequently asked questions

Which fields are always present?

In the OpenAPI schema (SerpOrganicItem) title and url are non-nullable strings but are not listed as required, while rank, display_url and snippet are nullable, so guard those three and still check that title and url are present before using them.

What is organic_count?

The number of rows in organic[] for that response.

Is the engine field reliable for Google?

Yes. Google responses carry engine "google", and google is one of the documented values of the engine field.

Can I fetch Google JSON today?

Google is callable today with a Bearer API key. The SERP API as a whole is not GA.

Parse it once, safely

Guard rank, display_url and snippet, and the same parser works for every organic engine.