---
title: "Response Schema"
description: "ResultsPage, Suggestions, Place, App, Trends and the rest: every type the SERP API returns, field by field."
---

> Every apinoa docs page as markdown: https://apinoa.com/llms.txt (all in one file: https://apinoa.com/llms-full.txt; this API family in one file: https://apinoa.com/docs/serp/llms.txt)

Each engine returns one shared set of types. A field means the same thing on every engine.

Optional fields are genuinely optional: **absent means the page did not say**. A missing `rating` means no stars
were shown; it does not mean zero stars. Times are ISO 8601 in UTC. Every object may carry `ext`, which holds
facts only that engine has, under the engine's own names.

| Operation | Returns |
|---|---|
| `search` | [`ResultsPage`](#resultspage) (app stores: [`AppsPage`](#appspage)) |
| `suggestions` | [`Suggestions`](#suggestions) |
| `places` · `place` · `reviews` | [`PlacesPage`](#placespage) · [`Place`](#place) · [`PlaceReviewsPage`](#placereviewspage) |
| `app` · `reviews` (app stores) | [`App`](#app) · [`AppReviewsPage`](#appreviewspage) |
| `explore` · `trending` (Google Trends) | [`TrendsExplore`](#trendsexplore) · [`TrendingPage`](#trendingpage) |

Google Shopping returns the marketplace types `SearchResult`, `Product` and `ReviewPage`, described in the
[Marketplace Response Schema](/docs/api-reference/marketplaces/response-schema).

## ResultsPage

One results page, holding every block in the order the page showed it.

| Field | Type | Notes |
|---|---|---|
| `engine` | string | `google` `bing` `yahoo` `duckduckgo` `yandex` `baidu` `naver` `yahoo-japan` `seznam` `daum` `sogou` |
| `query` | string | the query as asked; for a reverse-image search, what the engine named the image |
| `type` | string | `web` `news` `images` `videos` `image` |
| `outcome` | string | `results`, or `noResults` when the engine said it found nothing. A blocked or unreadable page is an error, never `noResults` |
| `country` `lang` `device` `timeRange` `safe` | string? | the inputs that framed the search, echoed back |
| `image` | string? | the image a reverse-image search ran on |
| `correctedQuery` | string? | what the engine actually searched, when it rewrote the query ("Showing results for …") |
| `totalResults` | integer? | only when the page states it ("About 1,230,000 results") |
| `page` | integer | 1 for the first page |
| `items` | Item[] | every block, in page order. See below |
| `cursor` | string? | the next page. Pass it alone as `cursor` |
| `fetchedAt` | string | when the page was read |

Every item has `type`, `rank` (its 1-based place among all items on the page) and `ext`. The rest depends on
`type`:

| `type` | Fields |
|---|---|
| `organic` | `position` (among organic results only, counting on across pages), `url`, `title`, `snippet?`, `site?`, `displayUrl?`, `date?`, `sitelinks?`, `thumbnail?`, `image?`, `imageWidth?`, `imageHeight?`, `images?`, `durationSec?`, `lang?`, `favicon?`, `badges?`, `facts?`, `rating?`, `ratingScale?`, `reviewCount?` |
| `ad` | `block?` (`top` `bottom` `side`), `url`, `title`, `snippet?`, `advertiser?`, `displayUrl?`, `sitelinks?`, `thumbnail?`, `phone?`, `extensions?`, `favicon?`, `badges?`, `rating?`, `reviewCount?`, `promotion?` |
| `news` | `url`, `title`, `snippet?`, `source?`, `sourceUrl?`, `sourceLogo?`, `date?`, `thumbnail?`, `favicon?` |
| `image` | `imageUrl`, `thumbnail?`, `width?`, `height?`, `title?`, `url?` (the page it is on), `source?`, `date?`, `format?`, `favicon?` |
| `video` | `url`, `title`, `snippet?`, `source?`, `channel?`, `channelUrl?`, `avatar?`, `date?`, `durationSec?`, `views?`, `viewsText?`, `thumbnail?`, `embedUrl?`, `preview?`, `favicon?` |
| `topStories` `videoCarousel` `imagePack` `shopping` `twitter` `discussions` | `title?`, `items` (the block's entries), `sponsored?`, `moreUrl?`, `total?` |
| `peopleAlsoAsk` | `title?`, `questions`: `{question, answer?, url?, title?}[]` |
| `relatedSearches` | `title?`, `queries`: string[] |
| `knowledgePanel` | `title`, `subtitle?`, `description?`, `source?`, `facts?`, `images?`, `website?`, `links?` |
| `localPack` | `places`: [Place](#place)[], `moreUrl?`, `total?` |
| `aiOverview` | `answer`: the [Answer](/docs/api-reference/answers/response-schema#answer) type of the AI Answers API, unchanged |
| `other` | `kind` (the engine's own name for the block), `title?`, `text?`, `links?` |

`sitelinks` and `links` are `{url, title?, snippet?}[]`. `facts` are `{label, value}[]`, kept in the order shown.
`badges` are the labels the page puts on a result, copied word for word. `rating` uses the page's own scale.
`ratingScale` gives the top of that scale when the page states it (`8.1/10` → `10`). A block the schema has no
shape for yet comes back as `other`. It is never dropped.

## Suggestions

| Field | Type | Notes |
|---|---|---|
| `engine` | string | |
| `query` | string | what was typed |
| `country` `lang` | string? | echoed when set |
| `suggestions` | array | `{text, type?}`: the engine's suggestions, in its order. `type` is the engine's own kind (query, entity…) where it states one |

## Place

A business or point of interest.

| Field | Type | Notes |
|---|---|---|
| `id` | string | the engine's stable place id; pass it to `place` and `reviews` |
| `name` | string | |
| `url` | string? | the place's page on the engine |
| `address` | object? | `{full?, street?, city?, region?, postalCode?, country?}` |
| `lotAddress` | string? | Korea's lot-number address, shown beside the road address |
| `coordinates` | object? | `{lat, lng}` |
| `categories` | string[]? | |
| `rating` `reviewCount` | number? | stars out of 5, and the count beside them |
| `priceLevel` | string? | as shown: `$$`, `₩₩` |
| `phone` `website` | string? | |
| `hours` | array? | `{day, hours}`, one per day listed, times as shown |
| `status` | string? | `open` `closed` `temporarilyClosed` `permanentlyClosed` |
| `statusText` | string? | the open-now line as worded ("Closed · Opens 7 AM") |
| `photos` | string[]? | the photos the page carried; `photoCount` is how many the place has in all |
| `attributes` | array? | `{group?, label, value?}`: amenities, service options, payment |
| `description` `neighborhood` `logo` | string? | |
| `verifiedOwner` | boolean? | the owner claimed the listing |
| `reviewsUrl` | string? | the page with the place's reviews |
| `lang` | string? | echoed |

## PlacesPage

| Field | Type | Notes |
|---|---|---|
| `engine` `query` | string | |
| `outcome` | string | `results` or `noResults` |
| `type` | string? | `maps` (the map's list) or `local` (Google's local results) |
| `location` `near` `country` `lang` | string? | echoed |
| `places` | [Place](#place)[] | |
| `page` | object | `{index, size, total?}`. `total` appears only when the engine states a count |
| `cursor` | string? | the next page |
| `fetchedAt` | string | |

## PlaceReviewsPage

| Field | Type | Notes |
|---|---|---|
| `engine` `placeId` | string | |
| `summary` | object? | `{average, count?, distribution?}` |
| `starCounts` | object? | star → number of reviews, as stated (`{"5": 2409, …}`) |
| `sort` | string? | |
| `page` | object | `{index, size, total?}` |
| `reviews` | array | see below |
| `cursor` | string? | |
| `fetchedAt` | string | |

A review has the same fields as a marketplace product review: `id?`, `author?`, `authorAvatarUrl?`, `rating?`,
`title?`, `body?`, `date?`, `helpfulCount?`, `language?`, `images`, `reply?` (`{body, date?, author?}`, the
owner's answer). Places add `authorId?`, `authorUrl?` and `pinned?`. A place review may have no stars
(Naver visitors often leave keywords instead), and then `rating` is absent, never `0`.

## AppsPage

The `search` result of Google Play and the App Store.

| Field | Type | Notes |
|---|---|---|
| `engine` | string | `google-play` `app-store` |
| `query` | string | |
| `outcome` | string | `results` or `noResults` |
| `country` `lang` | string? | echoed |
| `apps` | array | each one an [App](#app) as a list shows it, plus `rank` |
| `page` | object | `{index, size, total?}` |
| `cursor` | string? | |
| `fetchedAt` | string | |

## App

| Field | Type | Notes |
|---|---|---|
| `id` | string | Play's package name (`com.strava`), Apple's numeric id (`426826309`) |
| `name` | string | |
| `url` `icon` `video` | string? | |
| `developer` | object? | `{id?, name, url?, website?, email?, address?}` |
| `summary` | string? | the one line under the name |
| `description` `whatsNew` | string? | |
| `screenshots` | string[]? | |
| `categories` | string[]? | the main one first |
| `rating` | object? | `{average, count?}` |
| `starCounts` | object? | star → number of ratings |
| `editorsChoice` | boolean? | |
| `price` | object? | `{currency, amount}`; a free app is `amount: 0` |
| `inAppPurchases` | boolean? | |
| `contentRating` `version` `requires` | string? | as shown ("Teen", "12+", "Requires iOS 16.0 or later") |
| `releasedAt` `updatedAt` | string? | |
| `country` `lang` | string? | echoed |
| `related` `moreByDeveloper` | App[]? | the apps the page lists beside it, as a list shows them (`app` only) |
| `privacyPolicyUrl` | string? | `app` only |
| `chart` | object? | `{name, position}`: the app's place in a store chart (`app` only) |

## AppReviewsPage

| Field | Type | Notes |
|---|---|---|
| `engine` `appId` | string | |
| `sort` `country` `lang` | string? | echoed |
| `page` | object | `{index, size, total?}` |
| `reviews` | array | `id?`, `author?`, `rating`, `title?`, `body?`, `date?`, `helpfulCount?`, `images`, `reply?` (the developer's answer) |
| `cursor` | string? | |
| `fetchedAt` | string | |

## TrendsExplore

What Google Trends shows for up to five terms. Trends reports **relative** interest from 0 to 100, measured
against the busiest point of the request. A `0` is a value Trends stated, so it is returned as `0`.

| Field | Type | Notes |
|---|---|---|
| `terms` | string[] | as asked, in order |
| `country` `subregion` `timeRange` `category` `property` `lang` | | the inputs, echoed. No `country` means worldwide |
| `interestOverTime` | object? | `{points, averages?}`. A point is `{date, values, partial?, noData?}`, with one value per term |
| `interestByRegion` | object? | `{resolution?, measure?, regions}`. A region is `{code?, name, values, noData?, coordinates?}`. `measure` is `interest` for one term; with several terms it is `share`, each term's share of the region's searches |
| `related` | array? | `{term, topics?, queries?}`, each with `top` and `rising` lists of `{title, kind?, id?, value?, growth?, growthValue?, url?}` |
| `fetchedAt` | string | |

## TrendingPage

What is trending now in a country.

| Field | Type | Notes |
|---|---|---|
| `country` `subregion` `window` `category` `lang` | | echoed |
| `items` | array | `{rank, query, volume?, minVolume?, growth?, startedAt?, endedAt?, active?, categories?, related?, articles?}` |
| `fetchedAt` | string | |

`volume` is the search count as shown (`200K+`) and `minVolume` its lower bound. `articles` are
`{title, url, source?, date?, image?}`; with `include=articles`, every article Trends holds for each trend is
returned.
