---
title: "Response Schema"
description: "ResultsPage, Suggestions, Place, App, Trends 등 SERP API가 돌려주는 모든 타입의 필드별 설명."
---

> 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)

모든 엔진이 하나의 공통 타입 묶음을 돌려줍니다. 필드 하나는 모든 엔진에서 같은 뜻입니다.

선택 필드는 정말로 선택입니다. **없으면 페이지가 말하지 않았다는 뜻입니다.** `rating`이 없으면 별점이 표시되지 않은
것이지 별점이 0이라는 뜻이 아닙니다. 시각은 ISO 8601, UTC입니다. 모든 객체에는 `ext`가 있을 수 있고, 여기에는 그 엔진에만
있는 정보가 엔진 고유의 이름으로 들어갑니다.

| 오퍼레이션 | 반환 |
|---|---|
| `search` | [`ResultsPage`](#resultspage) (앱 스토어: [`AppsPage`](#appspage)) |
| `suggestions` | [`Suggestions`](#suggestions) |
| `places` · `place` · `reviews` | [`PlacesPage`](#placespage) · [`Place`](#place) · [`PlaceReviewsPage`](#placereviewspage) |
| `app` · `reviews` (앱 스토어) | [`App`](#app) · [`AppReviewsPage`](#appreviewspage) |
| `explore` · `trending` (Google Trends) | [`TrendsExplore`](#trendsexplore) · [`TrendingPage`](#trendingpage) |

Google Shopping은 마켓플레이스 타입인 `SearchResult`, `Product`, `ReviewPage`를 돌려줍니다.
[Marketplace Response Schema](/docs/api-reference/marketplaces/response-schema)를 보세요.

## ResultsPage

결과 페이지 하나입니다. 페이지에 나온 모든 블록을 나온 순서대로 담습니다.

| 필드 | 타입 | 설명 |
|---|---|---|
| `engine` | string | `google` `bing` `yahoo` `duckduckgo` `yandex` `baidu` `naver` `yahoo-japan` `seznam` `daum` `sogou` |
| `query` | string | 요청한 검색어. 이미지 검색에서는 엔진이 그 이미지를 부른 이름 |
| `type` | string | `web` `news` `images` `videos` `image` |
| `outcome` | string | `results`, 또는 엔진이 결과가 없다고 말한 경우 `noResults`. 막혔거나 읽지 못한 페이지는 에러이며 `noResults`가 아닙니다 |
| `country` `lang` `device` `timeRange` `safe` | string? | 검색 조건으로 쓴 입력을 그대로 돌려줍니다 |
| `image` | string? | 이미지 검색에 쓴 이미지 |
| `correctedQuery` | string? | 엔진이 검색어를 바꿔 검색했을 때 실제로 검색한 것("다음 검색결과 표시: …") |
| `totalResults` | integer? | 페이지가 밝힐 때만("검색결과 약 1,230,000개") |
| `page` | integer | 첫 페이지가 1 |
| `items` | Item[] | 모든 블록, 페이지 순서대로. 아래 참고 |
| `cursor` | string? | 다음 페이지. `cursor`만 넣어 넘깁니다 |
| `fetchedAt` | string | 페이지를 읽은 시각 |

모든 항목에는 `type`, `rank`(페이지의 모든 항목 중 1부터 센 위치), `ext`가 있습니다. 나머지는 `type`에 따라 다릅니다.

| `type` | 필드 |
|---|---|
| `organic` | `position`(일반 결과끼리의 순위, 다음 페이지로 이어서 셈), `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?`(이미지가 있는 페이지), `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`(블록 안의 항목), `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`: AI Answers API의 [Answer](/docs/api-reference/answers/response-schema#answer) 타입 그대로 |
| `other` | `kind`(엔진이 그 블록을 부르는 이름), `title?`, `text?`, `links?` |

`sitelinks`와 `links`는 `{url, title?, snippet?}[]`입니다. `facts`는 표시된 순서대로의 `{label, value}[]`입니다. `badges`는
페이지가 결과에 붙인 라벨을 글자 그대로 옮긴 것입니다. `rating`은 페이지의 척도를 그대로 쓰며, 페이지가 척도를 밝히면
`ratingScale`이 그 최댓값입니다(`8.1/10` → `10`). 아직 스키마에 형태가 없는 블록은 `other`로 돌려주며, 버리지 않습니다.

## Suggestions

| 필드 | 타입 | 설명 |
|---|---|---|
| `engine` | string | |
| `query` | string | 입력한 검색어 |
| `country` `lang` | string? | 넘겼으면 그대로 돌려줍니다 |
| `suggestions` | array | `{text, type?}`: 엔진의 추천 검색어, 엔진의 순서대로. `type`은 엔진이 밝힌 종류(검색어, 개체 등) |

## Place

업체나 관심 장소입니다.

| 필드 | 타입 | 설명 |
|---|---|---|
| `id` | string | 엔진의 고정 장소 id. `place`와 `reviews`에 넘깁니다 |
| `name` | string | |
| `url` | string? | 엔진의 장소 페이지 |
| `address` | object? | `{full?, street?, city?, region?, postalCode?, country?}` |
| `lotAddress` | string? | 도로명 주소 옆에 표시된 지번 주소 |
| `coordinates` | object? | `{lat, lng}` |
| `categories` | string[]? | |
| `rating` `reviewCount` | number? | 5점 만점의 별점과 그 옆의 리뷰 수 |
| `priceLevel` | string? | 표시된 그대로: `$$`, `₩₩` |
| `phone` `website` | string? | |
| `hours` | array? | `{day, hours}`. 표시된 요일마다 하나, 시간은 표시된 그대로 |
| `status` | string? | `open` `closed` `temporarilyClosed` `permanentlyClosed` |
| `statusText` | string? | 영업 상태 문구 그대로("영업 종료") |
| `photos` | string[]? | 페이지에 실린 사진. 장소의 전체 사진 수는 `photoCount` |
| `attributes` | array? | `{group?, label, value?}`: 편의 시설, 서비스, 결제 수단 |
| `description` `neighborhood` `logo` | string? | |
| `verifiedOwner` | boolean? | 업주가 등록을 인증했습니다 |
| `reviewsUrl` | string? | 장소 리뷰 페이지 |
| `lang` | string? | 넘긴 값 그대로 |

## PlacesPage

| 필드 | 타입 | 설명 |
|---|---|---|
| `engine` `query` | string | |
| `outcome` | string | `results` 또는 `noResults` |
| `type` | string? | `maps`(지도 목록) 또는 `local`(Google의 지역 결과) |
| `location` `near` `country` `lang` | string? | 넘긴 값 그대로 |
| `places` | [Place](#place)[] | |
| `page` | object | `{index, size, total?}`. `total`은 엔진이 개수를 밝힐 때만 |
| `cursor` | string? | 다음 페이지 |
| `fetchedAt` | string | |

## PlaceReviewsPage

| 필드 | 타입 | 설명 |
|---|---|---|
| `engine` `placeId` | string | |
| `summary` | object? | `{average, count?, distribution?}` |
| `starCounts` | object? | 별점 → 리뷰 수, 밝힌 그대로(`{"5": 2409, …}`) |
| `sort` | string? | |
| `page` | object | `{index, size, total?}` |
| `reviews` | array | 아래 참고 |
| `cursor` | string? | |
| `fetchedAt` | string | |

리뷰는 마켓플레이스 상품 리뷰와 같은 필드를 씁니다: `id?`, `author?`, `authorAvatarUrl?`, `rating?`, `title?`, `body?`,
`date?`, `helpfulCount?`, `language?`, `images`, `reply?`(`{body, date?, author?}`, 업주의 답글). 장소 리뷰에는
`authorId?`, `authorUrl?`, `pinned?`가 더 있습니다. 장소 리뷰에는 별점이 없을 수 있으며(Naver 방문자는 별점 대신 키워드를
남기는 경우가 많습니다), 그러면 `rating`이 없고 `0`으로 채우지 않습니다.

## AppsPage

Google Play와 App Store의 `search` 결과입니다.

| 필드 | 타입 | 설명 |
|---|---|---|
| `engine` | string | `google-play` `app-store` |
| `query` | string | |
| `outcome` | string | `results` 또는 `noResults` |
| `country` `lang` | string? | 넘긴 값 그대로 |
| `apps` | array | 목록에 보이는 [App](#app)에 `rank`를 더한 것 |
| `page` | object | `{index, size, total?}` |
| `cursor` | string? | |
| `fetchedAt` | string | |

## App

| 필드 | 타입 | 설명 |
|---|---|---|
| `id` | string | Play는 패키지 이름(`com.strava`), Apple은 숫자 id(`426826309`) |
| `name` | string | |
| `url` `icon` `video` | string? | |
| `developer` | object? | `{id?, name, url?, website?, email?, address?}` |
| `summary` | string? | 이름 아래 한 줄 소개 |
| `description` `whatsNew` | string? | |
| `screenshots` | string[]? | |
| `categories` | string[]? | 주 카테고리가 먼저 |
| `rating` | object? | `{average, count?}` |
| `starCounts` | object? | 별점 → 평가 수 |
| `editorsChoice` | boolean? | |
| `price` | object? | `{currency, amount}`. 무료 앱은 `amount: 0` |
| `inAppPurchases` | boolean? | |
| `contentRating` `version` `requires` | string? | 표시된 그대로("Teen", "12+", "Requires iOS 16.0 or later") |
| `releasedAt` `updatedAt` | string? | |
| `country` `lang` | string? | 넘긴 값 그대로 |
| `related` `moreByDeveloper` | App[]? | 페이지가 옆에 보여 주는 앱들, 목록에 보이는 형태로(`app`만) |
| `privacyPolicyUrl` | string? | `app`만 |
| `chart` | object? | `{name, position}`: 스토어 차트에서의 순위(`app`만) |

## AppReviewsPage

| 필드 | 타입 | 설명 |
|---|---|---|
| `engine` `appId` | string | |
| `sort` `country` `lang` | string? | 넘긴 값 그대로 |
| `page` | object | `{index, size, total?}` |
| `reviews` | array | `id?`, `author?`, `rating`, `title?`, `body?`, `date?`, `helpfulCount?`, `images`, `reply?`(개발자의 답글) |
| `cursor` | string? | |
| `fetchedAt` | string | |

## TrendsExplore

Google Trends가 검색어 최대 5개에 대해 보여 주는 것입니다. Trends는 요청 안에서 가장 많이 검색된 시점을 기준으로 한
**상대** 관심도를 0부터 100까지로 나타냅니다. `0`도 Trends가 밝힌 값이므로 `0`으로 돌려줍니다.

| 필드 | 타입 | 설명 |
|---|---|---|
| `terms` | string[] | 요청한 순서대로 |
| `country` `subregion` `timeRange` `category` `property` `lang` | | 넘긴 값 그대로. `country`가 없으면 전 세계 |
| `interestOverTime` | object? | `{points, averages?}`. 점 하나는 `{date, values, partial?, noData?}`이고 검색어마다 값이 하나 |
| `interestByRegion` | object? | `{resolution?, measure?, regions}`. 지역 하나는 `{code?, name, values, noData?, coordinates?}`. 검색어가 하나면 `measure`가 `interest`, 여러 개면 `share`(그 지역 검색에서 각 검색어가 차지하는 비율) |
| `related` | array? | `{term, topics?, queries?}`. 각각 `top`과 `rising` 목록이 있고 항목은 `{title, kind?, id?, value?, growth?, growthValue?, url?}` |
| `fetchedAt` | string | |

## TrendingPage

한 나라에서 지금 뜨는 검색어입니다.

| 필드 | 타입 | 설명 |
|---|---|---|
| `country` `subregion` `window` `category` `lang` | | 넘긴 값 그대로 |
| `items` | array | `{rank, query, volume?, minVolume?, growth?, startedAt?, endedAt?, active?, categories?, related?, articles?}` |
| `fetchedAt` | string | |

`volume`은 표시된 검색량(`200K+`)이고 `minVolume`은 그 하한입니다. `articles`는 `{title, url, source?, date?, image?}`이며,
`include=articles`를 주면 트렌드마다 Trends가 가진 기사를 모두 돌려줍니다.
