---
title: 검색결과 조회 API(/serp) 활용 가이드
description: "SERP API는 입력한 키워드의 최근 검색 결과를 반환합니다. 구글 검색결과 페이지(SERP)에 **어떤 블록이, 어떤 순서로, 어떤 내용으로** 노출되었는지를 반환하는 API입니다. 단, 이는 실시간 스크래핑이 아니라 사전에 리스닝마인드 플랫폼에서 수집·저장된 최신 SERP 스냅샷을 반환합니다. features 파라미터로 특정 feature 타입 1개(예: ai_overview)만 필터링해 받을…"
url: "https://kr.listeningmind.com/data-api/api-reference/serp-api/"
updated: "2026-10-16"
category: API 레퍼런스
---

# 검색결과 조회 API(/serp) 활용 가이드

SERP API는 입력한 키워드의 최근 검색 결과를 반환합니다. 구글 검색결과 페이지(SERP)에 **어떤 블록이, 어떤 순서로, 어떤 내용으로** 노출되었는지를 반환하는 API입니다. 단, 이는 실시간 스크래핑이 아니라 사전에 리스닝마인드 플랫폼에서 수집·저장된 최신 SERP 스냅샷을 반환합니다. features 파라미터로 특정 feature 타입 1개(예: ai_overview)만 필터링해 받을 수 있습니다.

## 핵심 특징 요약

SERP API는 키워드를 입력했을 때의 최신 구글 SERP Feature(서프 피처)를 반환합니다. 구글 검색 결과 페이지에서 전통적인 텍스트 형태의 파란색 링크(블루링크) 외에 추천 스니펫, 이미지, 지도, 관련 질문, AI 개요 등 추가로 표시되는 모든 검색 결과 요소를 포함합니다.

| **항목** | **상세** |
| --- | --- |
| 엔드포인트 | POST /serp |
| 요청 키워드 수 | 1개 |
| 반환 형식 | data: objects[] (SERP 노출 순서대로 정렬된 블록 배열) - 실시간 크롤 아님 |
| 반환 기본 개수 | 20 (SERP 노출 상위 20개 스니펫 수) |
| 반환 개수 (선택) | 10 (SERP 상위 10개 스니펫) or 20 (SERP 상위 20개 스니펫) |
| 요청 환경(디바이스) | mobile 고정 ( 데스크톱 검색 결과는 미지원) |
| 지원 국가(gl) | kr (한국) / jp (일본) / us (미국) |
| 과금 방식 | 입력 키워드 1개당 30 크레딧 + 출력 크레딧 없음 |

주의

- **실시간이 아닙니다.** 마지막 수집 시점의 스냅샷입니다. 산출물에 "현재 구글 검색결과"라고 쓰면 안 되고, "최근 수집된 SERP 스냅샷 기준"으로 표기해야 합니다.
- **키워드 1개 = 1회 호출입니다.** 100개 키워드를 보려면 100회 호출(=1,000 크레딧)이 필요합니다. 초당 3회 제한을 함께 고려해 배치를 설계하세요.
- **`data[]`는 랭킹 리스트가 아니라 "페이지 내 콘텐츠 블록 배열"입니다.** 오가닉 결과만 들어있는 것이 아니라, AI Overview·이미지팩·PAA·영상 등 **비(非)오가닉 블록이 노출 순서대로 섞여** 들어옵니다

1.

## 검색결과 조회 API(/serp) 는 언제 사용하나

| **사용자**** ****질문** | **사용 features** | 확인할 필드 |
| --- | --- | --- |
| 이 키워드에 AI Overview가 뜨나? 뭐라고 답하고 누굴 인용하나? (GEO) | ai_overview | `text_blocks`, `references[].source/url` |
| 1페이지를 어떤 도메인이 점유하고 있나? (SEO 경쟁분석) | organic_results | `position`, `site_name`, `url` |
| 우리 콘텐츠가 답해야 할 실제 질문은? (콘텐츠 브리프·FAQ) | people_also_ask_for | `items[].question`, `snippet`, `emphasis` |
| 동영상 선호도가 높나? 어떤 비디오가 노출되나? | `video_results`, `short_videos` | `channel`, `source`, `date` |
| 브랜드 SERP에 우리 자산(지식패널·앱)이 잡히나? | `knowledge_panel`, `app_results` | `cards[]._func`, `items[].rating` |
| 이 키워드는 뉴스성 이슈인가? | top_stories | items[].carousels[].date |
| 비주얼·이미지 의존도가 높은 키워드인가? | images | `grid[].source`, `landing_url` |

### **`/keyword_info`와의 역할 분담**

키워드 정보 조회(/keyword_info)의 "features"필드에서 제공하는 정보는 SERP feature의 "존재 여부(0/1)"입니다. 그 features의 실제 내용(문구·인용처·URL·질문)까지 구체적으로 확인하려면 SERP API를 활용합니다.

`/keyword_info`로 후보 키워드를 스크리닝(1회 최대 1,000개) → `f_ai_overview` 등이 켜진 키워드만 골라 `/serp`로 심층 조회합니다.

## 요청 파라미터 (Request)

### 파라미터 상세

| **파라미터** | **타입** | **필수** | **기본값** | **설명** |
| --- | --- | --- | --- | --- |
| keywords | string | Y | – | 조회할 키워드 1개, 영어는 소문자 권장 |
| gl | string | Y | – | 국가 코드: “kr” / “jp” / “us” 선택 1개 |
| num | integer | N | 20 | SERP에 노출된 결과 수 10 또는 20 |
| device | string | N | mobile | 요청 환경으로 mobile만 허용 |
| features | string | N | volume_avg | 응답에 포함할 SERP features 타입 지정, 최대 1개, 미지정이거나 빈 배열이면 전체 반환 |

### 파라미터 사용 시 주의사항

- **`features`는 1개까지만.** 2개 이상 넣으면 `422 Validation Error`(`too_long`)가 반환됩니다. 여러 feature가 필요하면 **필터 없이 전체를 받아 클라이언트에서 나누는 편이 유리**합니다(과금은 필터 유무와 관계없이 동일).
- **`features`는 단일 문자열도 허용**됩니다. `"features": "ai_overview"` = `"features": ["ai_overview"]`.
- **`device`는 `mobile` 고정**입니다. 모든 산출물에 "모바일 SERP 기준"이라는 단서를 달아야 하며, 데스크톱에서만 노출되는 형태는 이 데이터로 판단할 수 없습니다.
- **한글 키워드는 리터럴 한글 그대로** 전송하세요. 유니코드 이스케이프(`uXXXX`)로 보내면 매칭에 실패해 빈 결과가 나올 수 있습니다.
- **다국가 비교는 `gl`을 바꿔 재호출**해야 합니다. 한 나라 결과로 다른 나라를 추론하지 마세요(각각 별도 과금).

### features 선택 기준

| **features 지정** | **반환 결과** |
| --- | --- |
| 미지정 / null / [ ] | 해당 SERP의 **모든 블록** (노출 순서대로) |
| 값 1개 지정  (예: `["ai_overview"]`) | **그 타입의 블록만** 반환. 원본 `sequence` 번호는 그대로 유지 |
| 값 2개 이상 | 요청 실패 (`422`) |

필터를 걸어도 과금은 같습니다. **탐색 단계에서는 필터 없이 전체를 받고, 운영 파이프라인에서 특정 블록만 적재할 때 필터를 쓰는 것**이 비용 효율적입니다.

### 각 feature별 주요 반환 필드 요약

| SERP features | 블록 type | 주요 반환 필드 | 대표 용도 |
| --- | --- | --- | --- |
| ai_overview | ai_overview | `text_blocks[]`(`type`: paragraph/list, `snippet`, 중첩 `list`), `references[]`(`title`, `snippet`, `source`, `url`) | GEO — AI 답변 노출 여부·서술 내용·인용 출처 |
| organic_results | organic_results | `position`, `site_name`, `title`, `url`, `snippet`, `displayed_link`, `date`, `thumbnail`, `refinements[]`, `rating`, `images[]` | SEO 랭킹·경쟁 도메인·스니펫 분석 |
| people_also_ask_for | people_also_ask_for | `items[].question` (+ 펼쳐진 항목은 `title`, `url`, `snippet`, `displayed_link`, `emphasis[]`) | FAQ·콘텐츠 브리프·Q&A 커버리지 |
| people_also_search_for | people_also_search_for | items[].query | 연관 키워드 확장 |
| related_searches | related_searches | items[].query | 롱테일 변형 확장 |
| video_results | video_results | `items[]`(`title`, `url`, `source`, `channel`, `date`, `duration`) | 영상 점유·채널 경쟁 |
| short_videos | short_videos | `carousels[]`(`title`, `url`, `source`, `channel`) | 숏폼(Shorts/TikTok) 점유 |
| images | images | `grid[]`(`attrid`, `alt`, `landing_url`, `source`) | 이미지팩 점유·비주얼 수요 |
| knowledge_panel | knowledge_panel | `cards[]`(`_func`: header/thumbnails/fact/description/stats, `title`, `attrid`) | 엔티티 인식 여부(브랜드·인물) |
| top_stories | top_stories | `items[].carousels[]`(`title`, `url`, `date`) | 뉴스성·이슈성 판단 |
| app_results | app_results | `title`, `items[]`(`title`, `url`, `rating.rating_value`, `rating.rating_count`) | 앱 SERP 노출·평점 |
| sitelinks | sitelinks |  | 브랜드 내비게이션 자산 |
| featured_snippet | featured_snippet |  | 상단 피처드 스니펫 노출 확보 |

### 필터로는 지정할 수 없지만 전체 조회 시 반환되는 블록

`features` 지정 호출할 수는 없지만, 필터 없이 조회하면 실제로 반환되는 타입이 있습니다.

| 블록 `type` | 관찰 키워드 | 주요 필드 |
| --- | --- | --- |
| `local_results` | 삼성전자, 우체국 | `sequence`, `type`, `ved` (본문 필드 없이 자리만 표시) |
| `google_play` | 카카오톡 | `title`, `url`, `snippet`, `rating` |
| `recipes` | 계란찜 만드는 법 | `grid[]`(`title`, `source`, `rating`, `time`, `url`) |

## 요청 예시

```
{
  "keyword": "냉장고",
  "gl": "kr",
  "num": 20,
  "device": "mobile",
  "features": ["ai_overview"]
}
```

## 응답 데이터 구조 (Response)

```
{
  "result": "OK",
  "reason": "SUCCESS",
  "source": "listeningmind-data-api",
  "version": "0.0.56",
  "user_type": "data",
  "request_at": "2026-08-19T04:36:51.720Z",
  "request_detail": {
    "keyword": "삼성전자",
    "gl": "kr",
    "num": 20,
    "device": "mobile",
    "features": ["people_also_ask_for"]
  },
  "cost_detail": {
    "input_cost": 30, "input_count": 1, "input_total_cost": 30,
    "output_cost": 0, "output_count": 1, "output_total_cost": 0,
    "total_cost": 30
  },
  "used_credits": 13321361,
  "collected_at": "2026-08-26T21:3318.361Z",
  "data": [
    {
      "sequence": 2,
      "type": "people_also_ask_for",
      "ved": { "type": 10041 },
      "items": [
        { "question": "삼성전자를 지금 사면 얼마인가요?" },
        { "question": "삼성전자의 평균 월급은 얼마인가요?" }
      ]
    }
  ]
}
```

### 원본 수집 타임스탬프(collected_at) : 검색결과 언제 수집했나

리스닝마인드가 원본을 수집한 타임스탬프를 확인하세요. **ISO 8601 표준 형식의 날짜와 시간 데이터(UTC 기준)**입니다.

- **`2026-08-26`**: 연도, 월, 일을 나타냅니다. (예. **2026년 8월 26일**)
- **`T`**: 날짜(Date)와 시간(Time)의 경계를 나타내는 구분자입니다.
- **`21:33:18`**: 시, 분, 초를 나타냅니다. (**21시(오후 9시) 33분 18초**)
- **`.361`**: 밀리초(1000분의 1초) 단위입니다. (**361밀리초**)
- **`Z`**: **그리니치 표준시(UTC)**를 의미하는 시간대 기호입니다.

참고로 한국 시간은 UTC보다 9시간 빠르기 때문에 대한민국 표준시(KST)로 변환시, 다음과 같이 됩니다.
**2026년 8월 27일 목요일 오전 6시 33분 18.361초**

### 시퀀스 번호("sequence") : 전체 검색결과 중 몇 번째 블록인가

`sequence`는 **원본 SERP의 순서 번호("sequence" : 2)**입니다. 만약 필터를 걸어 순서 번호는 검색결과 스냅샷 원본과 동일하게 유지됩니다. 즉 필터 응답시에도 "이 블록이 전체 검색결과페이지 중 몇 번째에 있었는지"를 알 수 있습니다.

### 응답 데이터 구조 개요

| **최상위**** ****필드** | **타입** | **설명** |
| --- | --- | --- |
| sequence | integer | 페이지 내 노출 순서 (오가닉·비오가닉을 통틀어 매겨짐) |
| type | string | 블록 종류 (`organic_results`, `ai_overview`, `images` …) |
| ved | object | 구글 내부 블록 식별자(`{"type": 22}` 형태). 블록 종류 , 위치 구분의 보조 키로만 사용 |
| position | integer | **`organic_results`에만 존재.** 오가닉 결과 내 순위(1부터) |

**`sequence`와 `position`을 혼동하지 마세요.** `sequence`는 "화면에서 몇 번째로 보이는가", `position`은 "오가닉 검색 결과에서 몇 위인가"입니다. 예: `다이어트 방법`에서 오가닉 1위(`position: 1`)의 `sequence`는 **4** 인 경우, 오가닉 결과 위에 AI Overview·영상·PASF(People Also Search For)가 먼저 노출되는 것을 의미합니다.

### `organic_results`

```
{
  "sequence": 1, "type": "organic_results", "position": 1,
  "ved": { "type": 22 },
  "site_name": "만개의레시피",
  "displayed_link": "https://m.10000recipe.com › recipe",
  "title": "식당에서 먹던 맛과 비주얼 그대로, 폭탄 계란찜 만드는 법",
  "url": "https://m.10000recipe.com/recipe/6872350",
  "snippet": "계란 3개 · 소금 1/3큰술 · 설탕 1/3큰술 · 대파 적당량 …",
  "rating": { "rating_value": "5.0", "rating_count": "(673)" },
  "date": "2022. 7. 28.",
  "refinements": [ { "text": "냉장고세트" } ],
  "images": [ { "landing_url": "https://m.blog.naver.com/cshee32/222832208559" } ],
  "thumbnail": { "type": "image", "url": "…", "alt": "계란찜 만드는 법(출처: m.10000recipe.com)" }
}
```

| 필드 | 항상 존재 | 설명 |
| --- | --- | --- |
| `position`, `site_name`, `title`, `url` | O | 순위·출처명·제목·랜딩 URL |
| `snippet` | 거의 항상 | 검색결과 설명문 (실측 191건 중 190건) |
| `displayed_link` | 선택 | 화면에 표시되는 경로 표기 |
| `date` | 선택 | 콘텐츠 게시일 (표시된 경우만) |
| `rating` | 선택 | `rating_value`, `rating_count` — 리뷰·레시피형 결과 |
| `refinements` | 선택 | 결과 하위의 카테고리 세부링크 텍스트 |
| `images` | 선택 | 결과에 딸린 인라인 이미지들의 `landing_url` |
| `thumbnail` | 선택 | 썸네일 `type` / `url` / `alt` |

### `ai_overview`

```
{
  "sequence": 1, "type": "ai_overview", "ved": { "type": 171865 },
  "text_blocks": [
    { "type": "paragraph", "snippet": "냉장고는 식품이나 약품을 저온에서 보관하기 위한 …" },
    { "type": "list", "list": [
        { "snippet": "용량: 가구 구성원 수에 맞춰 적절한 용량을 선택해야 합니다." },
        { "snippet": "종류: 라이프스타일에 맞는 종류를 선택해야 합니다.",
          "list": [ { "snippet": "4도어, 양문형, 상냉동 하냉동, 빌트인 등이 있습니다." } ] }
    ] }
  ],
  "references": [
    { "title": "2025 냉장고 추천 구매가이드 …", "snippet": "냉장고를 고르기 전에 …",
      "source": "YouTube", "url": "https://www.youtube.com/watch?v=K6Wo5O-ZVXE" }
  ]
}
```

- `text_blocks[]` — AI 답변 본문. `type`이 `paragraph`면 `snippet`에 문장이 나오고, `list`면 `list[]`에 항목이 들어가며 **`list` 안에 `list`가 중첩**될 수 있습니다.
- `references[]` — **AI가 인용한 출처.** GEO 분석의 핵심 데이터로 `source`(매체명)와 `url`을 그대로 사용합니다.

### 키워드 확장형 블록 (`people_also_search_for`, `related_searches`)

```
{ "sequence": 3, "type": "people_also_search_for", "ved": { "type": 54107 },
  "items": [ { "query": "냉장고 영어" }, { "query": "소형냉장고" } ] }
```

두 타입 모두 `items[].query` 하나뿐이라 **그대로 시드 키워드 풀에 합칠 수 있습니다.**

### `people_also_ask_for`

```
{ "sequence": 2, "type": "people_also_ask_for", "ved": { "type": 10041 },
  "items": [
    { "question": "삼성전자의 평균 월급은 얼마인가요?" },
    { "question": "2026년 삼성전자 배당금은 얼마인가요?",
      "displayed_link": "https://stockevents.app",
      "url": "https://stockevents.app/kr/stock/005930.KQ/dividends",
      "title": "삼성전자 (005930.KQ) 2026년 배당: 내역, 배당락일 & 수익률",
      "snippet": "삼성전자의 배당금은 분기별 지급됩니다. …",
      "emphasis": ["주당 배당금은 ₩1,695"] }
  ] }
```

- 대부분 항목은 `question`만 갖습니다. **수집 시점에 펼쳐져 있던 항목만** 답변 필드(`title`/`url`/`snippet`/`emphasis`)를 함께 가집니다.
- `emphasis[]`는 구글이 굵게 강조한 정답 문구로, **"이 질문의 정답으로 인정된 표현"** 에 해당합니다.

### 영상형 블록 (`video_results`, `short_videos`)

```
{ "sequence": 6, "type": "video_results", "ved": { "type": 21807 },
  "items": [ { "title": "김치냉장고, 정작 중요한 정보는 …",
               "url": "https://www.youtube.com/watch?v=3OM1FdIYlIw",
               "source": "YouTube", "channel": "노써치",
               "date": "2주 전", "duration": "15:27" } ] }
```

- `video_results`는 `items[]`, `short_videos`는 **`carousels[]`** 키를 씁니다(구조는 유사하며 `duration` 없음).
- `date`가 `"2주 전"` 같은 **상대 표기**로 오는 경우가 많습니다. 절대 날짜가 필요하면 환산 후 `[추정]` 레이블을 붙이세요.
- `short_videos`의 `source`에는 `YouTube` 외 `TikTok`도 포함되며, TikTok 항목의 `url`은 원본이 아닌 구글 썸네일 프록시(`encrypted-vtbn0.gstatic.com`)일 수 있습니다.

### `images` / `recipes`

```
{ "sequence": 2, "type": "images", "ved": { "type": 1736 },
  "grid": [ { "attrid": "images universal", "alt": "LG SIGNATURE 상냉장고",
              "landing_url": "https://www.lge.co.kr/refrigerators/f904nd79e",
              "source": "LG전자" } ] }
```

두 타입 모두 `items`가 아니라 **`grid[]`** 를 씁니다. `images`는 이미지 파일 URL이 아닌 **랜딩 페이지 URL(`landing_url`)과 대체텍스트(`alt`)** 를 제공합니다.

### `top_stories`

```
{ "sequence": 1, "type": "top_stories", "ved": { "type": 25733 },
  "items": [ { "carousels": [
      { "title": "삼성전자 “가볍고 쓰기 편한 스마트 글라스…”", "date": "3시간 전",
        "url": "https://www.donga.com/news/amp/all/20260726/134367207/2" }
  ] } ] }
```

`items[] → carousels[]` **2단계 중첩**입니다. 파싱 시 `items[0].carousels`를 평탄화해야 기사 목록을 얻습니다.

### `knowledge_panel`

```
{ "sequence": 4, "type": "knowledge_panel",
  "cards": [ { "_func": "fact", "ved": { "type": 155735 }, "attrid": "lab/fact/1p/출생" } ] }
```

- 지식패널은 **여러 개의 `knowledge_panel` 블록으로 쪼개져** 반환됩니다(`손흥민` 실측: 6개 블록).
- 각 블록의 `cards[]._func`가 카드 종류(`header`, `thumbnails`, `fact`, `description`, `stats`)를 나타내며, **본문 값은 대부분 비어 있고 `title`·`attrid` 수준의 골격만** 제공됩니다. 지식패널은 값 추출보다 **"엔티티로 인식되는가 / 어떤 카드가 붙는가"** 판단에 쓰세요. `[실제데이터]`

### `app_results` / `google_play`

```
{ "sequence": 7, "type": "app_results", "ved": { "type": 17009 }, "title": "Apps",
  "items": [ { "title": "쿠팡(Coupang)-모바일 쇼핑",
               "rating": { "rating_value": "4.5", "rating_count": "(64만)" },
               "url": "https://play.google.com/store/apps/details?id=com.coupang.mobile&…" } ] }
```

`rating_count`는 숫자가 아니라 `"(64만)"` 같은 **표시 문자열**입니다. 정량 비교에는 파싱·정규화가 필요합니다.

## 주요 지표 해석

`/serp`는 지표를 계산해 주지 않습니다. **블록 배열에서 직접 지표를 만들어 쓰는 것**이 이 API의 사용법입니다. 아래는 `다이어트 방법`(kr, 2026-08-19 조회) 실측 응답으로 계산한 예시입니다

### 1) SERP 구성비 — "이 키워드는 무엇으로 채워져 있나"

| 블록 | 개수 | 비중 |
| --- | --- | --- |
| `organic_results` | 16 | 69.6% |
| `images` | 2 | 8.7% |
| `ai_overview` / `video_results` / `people_also_search_for` / `people_also_ask_for` / `related_searches` | 각 1 | 각 4.3% |
| **합계** | **23** | 100% |

**해석:** 비오가닉 블록이 약 30%를 차지 → 오가닉 1위를 잡아도 화면 점유율은 그만큼 희석됩니다.

### 2) 첫 오가닉의 `sequence` — 유효 노출 난이도

`다이어트 방법`의 오가닉 1위는 `position: 1`이지만 `sequence: 4`입니다. **위에 AI Overview·영상·PASF 3개 블록이 먼저** 놓입니다.

| 지표 | 계산식 | 해석 |
| --- | --- | --- |
| 오가닉 진입 깊이 | `첫 organic_results의 sequence − 1` | 값이 클수록 SEO 1위의 실효 가치가 낮음 (예시: **3**) |

### 3) AI Overview 인용 점유율 (GEO 핵심)

`references[]`의 `source`·도메인을 집계합니다.

- 인용 출처 **10건** — YouTube·굿라이프(2), 대한민국 정책브리핑, 삼성서울병원, 국민건강보험공단, 행복한내과, 나무위키, Instagram, 패션비즈, Vietnam.vn 각 1
- 그중 **4곳(정책브리핑·삼성서울병원·국민건강보험공단·나무위키)이 오가닉 결과에도 등장** → **인용-오가닉 중복률 40%**

| 지표 | 계산식 | 해석 |
| --- | --- | --- |
| 인용 점유율 | `자사 인용 수 ÷ references 총수` | AI 답변에서의 브랜드 지분 |
| 인용-오가닉 중복률 | `references 도메인 ∩ organic 도메인 ÷ references 총수` | 낮을수록 **SEO 순위와 무관한 인용 경로**가 크다는 뜻 → 별도 GEO 전략 필요 |

### 4) 오가닉 도메인 집중도

`site_name`(또는 `url` 호스트)으로 집계합니다. `다이어트 방법`은 16개 결과가 블로그·나무위키·한국소비자원·정책브리핑·삼성서울병원·국민건강보험공단 등으로 **분산**되어 지배 사업자가 없는, 신규 진입 여지가 있는 SERP입니다.

| 지표 | 계산식 | 해석 |
| --- | --- | --- |
| 도메인 집중도 | 상위 도메인 점유율 합 | 높으면 소수 매체가 장악 → 진입 난이도 ↑ |
| 자사 점유 | 자사 도메인의 `position` 목록 | 1페이지 내 다중 노출 여부 확인 |

### 5) 질문·연관어 확장량

| 소스 | 개수 | 활용 |
| --- | --- | --- |
| `people_also_ask_for` | 4 | 콘텐츠 H2·FAQ 초안 ("가장 빨리 살빼는 법?", "한달 만에 10kg 빼는 법?" …) |
| `people_also_search_for` | 6 | 시드 확장 ("현실적인 다이어트 방법", "학생 다이어트 방법" …) |
| `related_searches` | 6 | 롱테일 변형 ("쉬운 다이어트 방법", "다이어트 방법 종류" …) |

이 16개를 `/keyword_info`에 다시 넣어 검색량을 붙이면 **"질문 → 수요 크기"** 가 한 번에 정리됩니다.

### 6) 영상·숏폼 압력

`video_results` + `short_videos` 블록의 `sequence`가 작을수록(=상단) 텍스트 콘텐츠만으로는 상위 화면을 확보하기 어렵습니다. `channel` 집계로 **어떤 채널이 카테고리를 쥐고 있는지**도 함께 확인하세요.

> **레이블 원칙:** 위 지표는 모두 `data[]`에서 직접 센 값이므로 `[실제데이터]`입니다. 상대 날짜(`"2주 전"`)를 절대일로 환산하거나 스냅샷 수집일을 특정 시점으로 가정하는 순간 `[추정]`·`[가정]`으로 강등해 표기하세요.

---

## 활용 시나리오별 파라미터 조합

| 목적 | `features` | `gl` | 비고 |
| --- | --- | --- | --- |
| GEO — AI Overview 인용 모니터링 | `["ai_overview"]` | 대상국 1개 | 주기 반복 호출로 인용처 변화 추적 |
| SEO — 경쟁 도메인 분석 | 미지정(전체) | 대상국 1개 | `organic_results` + 비오가닉 블록을 함께 봐야 실효 점유율이 나옴 |
| 콘텐츠 브리프 작성 | `["people_also_ask_for"]` | 대상국 1개 | 질문 목록만 가볍게 축적 |
| 시드 키워드 확장 | 미지정(전체) | 대상국 1개 | PASF + related + PAA를 한 번에 회수 |
| 브랜드 SERP 자산 점검 | 미지정(전체) | 대상국 1개 | `knowledge_panel`·`app_results`·`top_stories` 동시 확인 |
| 다국가 비교 | 동일 조건 | `kr` → `jp` → `us` **각각 호출** | 국가별 별도 과금, 추론 금지 |

⚠️ **주의:** `features`에 2개 이상을 넣는 조합은 존재하지 않습니다. "AI Overview + 오가닉"이 필요하면 **필터 없이 전체 조회 1회**가 정답입니다(따로 2회 호출하면 20크레딧, 전체 조회 1회면 10크레딧).

---

## 오류 응답 처리

| 코드 | `reason` | 원인 | 대응 |
| --- | --- | --- | --- |
| `401` | `Invalid API key` | `LM-API-KEY` 헤더 누락·오타·만료 | 키 확인. dev/prod 엔드포인트별 키가 다를 수 있음 |
| `402` | `Payment Required` | 크레딧 소진 | 크레딧 충전 후 재시도 |
| `403` | `Not Authenticated` | 권한 없음 | 계정 권한·플랜 확인 |
| `422` | `Validation Error` | `features` 2개 이상, `gl` 허용값 위반, `num`이 10/20 외, `keyword` 빈 문자열 | `detail[].message` / `detail[].type`으로 원인 특정 |
| `429` | `Too Many Requests` | **`/serp` 초당 3회** 초과 | 1초 backoff 후 재시도 |
| `500` | `Internal Server Error` | 서버 오류 | 재시도, 지속 시 문의 |

**오류 응답 형식**

```
{
  "result": "FAILED",
  "reason": "Validation Error",
  "source": "listeningmind-data-api",
  "version": "0.0.56",
  "request_at": "2026-08-19T04:36:52.155Z",
  "detail": [
    { "message": "List should have at most 1 item after validation, not 2 ('body', 'features')",
      "type": "too_long" }
  ]
}
```

```
{
  "result": "FAILED",
  "reason": "Too Many Requests: Rate limit exceeded. '/serp' allows a maximum of 3 requests per seconds.",
  "source": "listeningmind-data-api",
  "version": "0.0.56",
  "request_at": "2026-08-19T04:34:39.331Z"
}
```

> **4xx/5xx 응답에는 과금이 발생하지 않습니다.** 오류 응답에는 `cost_detail` 자체가 없습니다. 기간별 호출량·에러율은 `GET /usage/summary?from=YYYY-MM-DD&to=YYYY-MM-DD`(KST 기준)로 확인할 수 있습니다.

---

## 자주 묻는 질문 (FAQ)

### Q1. `/serp`는 실시간 구글 검색결과인가요?

리스닝마인드 플랫폼에서 **최근 수집·저장된 스냅샷**을 반환합니다. 응답의 `request_at`은 "내가 API를 호출한 시각"일 뿐 **SERP가 수집된 시각이 아닙니다.** 산출물에는 "최근 수집 스냅샷 기준"으로 표기하고 "현재/실시간"이라고 쓰지 마세요. 정확한 수집 시간은 수집 시점 타임스탬프(collected_at)을 참고해 주세요. 특정 날짜를 선택해 검색결과를 호출할 수는 없습니다. 시점 변화를 보려면 **호출 결과를 직접 날짜별로 저장해 비교**해야 합니다.

### Q2. 키워드를 여러 개 한 번에 넣을 수 있나요?

안 됩니다. `/keyword_info`는 `keywords` **배열**(최대 1,000개)을 받지만 `/serp`는 `keyword` **문자열 1개**만 받습니다. N개 키워드 = N회 호출 = N×10 크레딧이며, **초당 3회** 제한을 고려해 배치 설계해 주세요.(100개 수집 시 최소 약 34초).

### Q3. `features`에 2개 이상 넣으면 어떻게 되나요?

`422 Validation Error`(`type: "too_long"`)로 실패합니다. 여러 블록이 필요하면 **`features`를 생략하고 전체를 받으세요.** 필터 유무와 관계없이 과금은 동일하므로 전체 조회가 유리합니다.

### Q4. `num`을 10으로 줄이면 응답이 가벼워지나요?

노출 순위 Top 10 보기(`num=10)`과 노출 순위 Top 20 보기(`num=20`)을 요청한 결과, **저장된 스냅샷의 깊이에 큰 차이가 없습니다.** 응답 크기를 줄이기 보다 `features` 필터를 사용해 동영상 블록만 보거나, PAA(People Also Asks)만 보거나 하는 등 선택해 응답 크기를 조정하세요.

### Q5. 데스크톱 검색결과도 볼 수 있나요?

 `device`는 `mobile` **고정값(const)** 입니다. 따라서 모든 분석은 모바일 SERP 기준이며, 데스크톱 전용 노출 형태는 이 데이터로 판단할 수 없습니다. 보고서에 "모바일 SERP 기준"을 명시하세요.

### Q6. `sitelinks`·`featured_snippet`은 왜 응답에 안 보이나요?

`features` 항목에 존재하지만 모든 결과에 모든 features 항목이 **관찰되는 것은 아닙니다.** 정보성 질의에서 과거 featured snippet이 차지하던 자리를 현재 `ai_overview`가 대체하는 패턴이 관찰됩니다. 특정 키워드의 노출 여부를 대량으로 확인하려면 `/keyword_info`의 `data_type: "all"` → `features`(`f_featured_snippet` 등 0/1 플래그)로 먼저 스크리닝한 후 SERP API를 활용해 ai_overview 원문을 수집하는 편이 효율적입니다.

### Q7. `features` 에 지표에 없는 `type`이 응답에 들어있습니다.

정상입니다. 필터로 지정할 수는 없지만 전체 조회 시 반환되는 블록이 있습니다 — `local_results`, `google_play`, `recipes`. 파서는 **알 수 없는 `type`을 만나도 실패하지 말고 원문 보존 후 건너뛰도록** 합니다.

### Q8. `sequence`와 `position`은 무엇이 다른가요?

`sequence`는 **페이지 전체에서의 노출 순서**(모든 블록 통합, 1부터), `position`은 **오가닉 결과 내 순위**이며 `organic_results` 블록에만 존재합니다. 오가닉 결과 1위여도 `sequence`가 4일 수 있습니다 — 오가닉 결과 위에 AI Overview·영상 등이 먼저 놓이기 때문입니다. **실효 노출 분석은 `sequence`로, 랭킹 리포트는 `position`으로** 하세요.

### Q9. `features` 필터를 걸면 `sequence`가 1부터 다시 매겨지나요?

아닙니다. **원본 SERP의 `sequence`가 그대로 유지**됩니다(예: `삼성전자`에 `people_also_ask_for` 필터를 걸면 `sequence: 2`). 필터 응답만으로도 해당 블록의 페이지 내 위치를 알 수 있습니다.

### Q10. 결과가 없는 키워드는 과금되나요?

과금되지 않습니다. 스냅샷이 없는 키워드는 `200 OK`에 `data: []`가 반환되고 `cost_detail`이 `input_count: 0`, `total_cost: 0`으로 내려옵니다. 다만 **`data: []`는 "검색결과가 없다"가 아니라 "저장된 스냅샷이 없다"** 는 의미이므로 시장 부재의 근거로 쓰면 안 됩니다 `[데이터공백]`. `4xx/5xx` 오류도 마찬가지로 과금되지 않습니다.

### Q11. 한글 키워드가 빈 결과로 나옵니다.

요청 본문에 **리터럴 한글**을 UTF-8로 그대로 담아야 합니다. `json.dumps(..., ensure_ascii=True)`로 `uXXXX` 이스케이프해 보내면 매칭에 실패할 수 있습니다. Python이라면 `json.dumps(body, ensure_ascii=False).encode("utf-8")`를 사용하세요.

### Q12. 여러 나라를 한 번에 볼 수 있나요?

`gl`은 1회 1개국(`kr`/`jp`/`us`)입니다. 국가별로 **별도 호출·별도 과금**이며, 한 국가 결과로 다른 국가를 추론하는 것은 금지입니다.
