How to get Google AI Mode answers as JSON
Google AI Mode is the conversational search interface where Google answers a question in full, cites the pages it used and, depending on intent, adds product cards, places, maps and videos. It is a different surface from AI Overview, the summary above an ordinary results page, and needs its own measurement.
Google’s own announcement says AI Mode uses a “query fan-out technique”: it splits a question into subtopics and runs many searches at once (Google, May 20, 2025, checked 2026-09-17). The practical consequence: the pages AI Mode cites can differ from the top organic results for your keyword, so ranking data alone will not tell you whether you appear. The Google AI Mode API lists every request and response field; this post walks one prompt through to stored rows.
Definitions
- AI Mode answer: the generated response Google shows in AI Mode for one prompt, returned as
result.text(andresult.markdownon request). - Source: a page in the answer’s source list, returned in
result.sources[]with a 1-indexedposition,url,labelanddescription. - Citation pill: an inline chip inside the answer text that links to one or more sources, returned in
result.citationPills[].
AI Mode vs AI Overview
Both come from Google, both cite sources, and both can change your traffic. They are still separate measurements.
| AI Overview | AI Mode | |
|---|---|---|
| Where it appears | Above the organic results on a Google results page | Its own conversational interface |
| How you request it | POST /v1/monitor/google with include.aioverview |
POST /v1/monitor/aimode |
| Async task type | GOOGLE |
AIMODE |
| Input field | query |
prompt |
| Pages | pages 1-10 for the organic results |
Not applicable |
| Targeting | country or gl, hl, location or uule, device desktop, mobile, ios or android |
country or gl, hl, location or uule, device desktop or mobile |
| Answer fields | aioverview.text, markdown, sources, citationPills, relatedLinks, videos, ads |
text, markdown, sources, citationPills, shoppingCards, inlineProducts, places, map, videos, ads |
| Base cost | $0.00103 for the search, +$0.00071 for the overview | $0.00206 |
AI Overview only appears for some queries, and aioverview is null in the response when none is available. AI Mode always produces an answer, so the useful questions are what it said and whom it cited. For the companion surface, see how to monitor Google AI Overviews.
The request
curl -X POST https://api.answerline.dev/v1/monitor/aimode \
-H "Authorization: Bearer $ANSWERLINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "best standing desks for a small home office",
"country": "US",
"location": "Austin,Texas,United States",
"device": "desktop",
"include": { "markdown": true }
}'
Request fields:
| Field | Type | Notes |
|---|---|---|
prompt |
string, 1-2,000 chars | Required. The question sent to AI Mode. |
country |
string | ISO 3166-1 alpha-2 code. Send country or gl. |
gl |
string | Google’s own name for the result geography; same codes, either case. Sending both with different values is a 400. |
hl |
string | Interface language, such as en, de or pt-BR. Overrides the language derived from the country. |
location |
string | Canonical City,Region,Country name from Google’s geotargets list. |
uule |
string | Pre-encoded UULE. Mutually exclusive with location. |
device |
desktop or mobile |
Defaults to desktop. |
include.html |
boolean | Adds result.html, a link to a copy of the AI Mode page as it was when the answer was captured. No extra cost. |
include.markdown |
boolean | Adds result.markdown. |
include.expandProducts |
boolean | Not available yet: a request that sets it is refused with a 400 and not charged. |
Unknown fields are rejected, so a typo such as "locaton" fails validation instead of being silently ignored. Supported country codes for this engine come from GET /v1/countries?model=aimode.
The response
A trimmed response looks like this:
{
"success": true,
"result": {
"text": "For a small home office, look for a desk with a compact footprint...",
"markdown": "For a small home office, look for a desk with a **compact footprint**...",
"sources": [
{ "position": 1, "url": "https://example.com/standing-desk-guide", "label": "Standing desk guide", "description": "How to choose..." }
],
"citationPills": [
{ "citationPillId": 1, "label": "Standing desk guide", "url": "https://example.com/standing-desk-guide", "domain": "example.com", "position": 1 }
],
"shoppingCards": [
{ "position": 0, "title": "Compact Standing Desk 48\"", "price": { "value": 299.99, "currency": "$", "raw": "$299.99" }, "store": "Example Store", "rating": 4.5, "reviews": "1.2k" }
]
}
}
What each block holds:
text/markdown: the answer. Usemarkdownwhen you want headings and lists preserved for display or for diffing structure.sources[]:position,url,label,description. This is the source rail.citationPills[]: one entry per (pill, source) pair. A chip that cites three sources appears as three entries sharing acitationPillId, each with its ownlabel,url,domainand apositionpointing intosources[]. The field is omitted when the answer has no pills.shoppingCards[]:title,priceandoldPrice(value,currency,raw),store,rating,reviews(a display string such as"2.3k"),thumbnail,productLink,snippet,snippet_links[]and a 0-indexedpositionin the carousel.inlineProducts[]: products rendered inside the answer text, with a 1-indexedposition,title,price,oldPrice,store,thumbnail,productLink.places[]: inline place cards withtitle,link,placeId,index,thumbnail,rating,reviews(an integer),type,priceLevel,address,status.map[]: place entries withgps_coordinates(latitude,longitude) plus the same descriptive fields.videos[]:title,link(timestamp parameters stripped),platform,channel,duration,thumbnail.ads: an object, not an array: a sectiontitleand anads[]list withtitle,url,position,price,store,rating,reviews.
Two indexing details catch people out. shoppingCards[].position is 0-indexed while inlineProducts[].position and sources[].position are 1-indexed; normalize before you store. And citationPills[].position refers to the source’s position in sources[], not to where the pill sits in the text.
Links Google served as redirects also carry a redirectLink beside the resolved URL. POST /v1/monitor/google/goto resolves one on demand, charges nothing.
Measuring citations
The core AI Mode metric for most teams is simple: for a fixed set of prompts, how often is my domain cited, and in which position?
import requests
from urllib.parse import urlparse
API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
def domain(url: str) -> str:
host = urlparse(url).hostname or ""
return host.removeprefix("www.")
def ai_mode(prompt: str, country: str = "US") -> dict:
r = requests.post(f"{API}/v1/monitor/aimode", headers=HEADERS,
json={"prompt": prompt, "country": country}, timeout=360)
r.raise_for_status()
return r.json()["result"]
def citation_row(prompt: str, result: dict, target: str) -> dict:
sources = result.get("sources", [])
positions = [s["position"] for s in sources if domain(s["url"]) == target]
pills = {p["citationPillId"] for p in result.get("citationPills", []) if p.get("domain", "").removeprefix("www.") == target}
return {
"prompt": prompt,
"cited": bool(positions),
"best_position": min(positions) if positions else None,
"source_count": len(sources),
"pill_count": len(pills),
}
Three measures come out of this and each answers a different question:
- Citation rate: the share of prompts where your domain is in
sources[]. Is the engine using you at all? - Best position: your lowest
positionin the source rail. Are you a primary or a supporting source? - Pill coverage: how many distinct
citationPillIdvalues point to you. Pills sit inside the text, next to the claim they support, so they show which statements you back.
Brand mentions are a separate measure. AI Mode has no entities[] field, so match your brand and competitor names in text with word boundaries and a list of aliases. Mentions vs citations covers why both matter and how they diverge.
Measuring products and places
For commerce prompts (“best X under $Y”, “X vs Y”), products are the answer. Record one row per product per run:
def product_rows(prompt: str, result: dict) -> list[dict]:
rows = []
for card in result.get("shoppingCards", []):
rows.append({"prompt": prompt, "block": "card", "rank": card["position"] + 1,
"title": card.get("title"), "store": card.get("store"),
"price": (card.get("price") or {}).get("value"), "rating": card.get("rating")})
for item in result.get("inlineProducts", []):
rows.append({"prompt": prompt, "block": "inline", "rank": item["position"],
"title": item.get("title"), "store": item.get("store"),
"price": (item.get("price") or {}).get("value"), "rating": None})
return rows
price.value and price.currency are structured, but keep price.raw as well when it is present: it is the text the shopper saw.
Local prompts (“physiotherapist near downtown Denver”, “family hotels in Kyoto”) return places[] and map[]. Store placeId as the stable key, since business names are not unique, and run the same prompts with different location values to see how the answer shifts across a metro area. The local AI answers guide walks through a geography sweep.
Running AI Mode on a monitoring set
Synchronous calls are convenient for testing. For a monitoring set, use async tasks: they do not hold a connection open.
curl -X POST https://api.answerline.dev/v1/async/task/batch \
-H "Authorization: Bearer $ANSWERLINE_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{ "taskType": "AIMODE", "idempotencyKey": "aimode-2026-09-17-desks-us",
"payload": { "prompt": "best standing desks for a small home office", "country": "US" },
"webhook": { "url": "https://your-app.example/hooks/answerline" } },
{ "taskType": "GOOGLE", "idempotencyKey": "google-2026-09-17-desks-us",
"payload": { "query": "best standing desks for a small home office", "country": "US", "include": { "aioverview": {} } },
"webhook": { "url": "https://your-app.example/hooks/answerline" } }
]'
A batch takes 1 to 500 tasks, validates each independently and returns results in input order. The example pairs each AI Mode prompt with a Google Search task for the same phrase, with AI Overview enabled, so one pipeline captures both surfaces under the same geography. When a task finishes, the webhook receives the task with its response; you can also poll GET /v1/async/task/{taskId}. Build idempotencyKey from date, engine, prompt id and market so a retried batch does not create duplicates (a duplicate key returns 409). Details: async tasks, webhooks and idempotency keys explained.
Cost
AI Mode and Google Search cost $2.06 and $1.03 per 1,000 tasks on every tier, deducted from your prepaid balance (see /pricing for the tiers and /docs/credits for how charges are reported):
| Request | Price at Starter |
|---|---|
| AI Mode request | $0.00206 |
| Google Search task with AI Overview, 1 page | $0.00174 |
An accepted request reserves its maximum possible cost and is charged the actual cost when it succeeds; a failed request is charged nothing. For a budget, multiply prompts × markets × runs per month by the per-1,000 dollar price. 200 prompts in 2 markets, weekly (about 4.3 runs a month), without product expansion, is roughly 1,720 tasks ≈ $3.54 a month at Starter-tier prices. Planning monitoring costs goes deeper.
Uses
- Publishers track whether articles still enter
sources[]for the questions that used to send them search clicks, and which competing domains replace them. - Commerce brands record which products appear in
shoppingCards[]andinlineProducts[]for category prompts, at which price and store, week over week. - Local businesses and agencies watch
places[]andmap[]for service prompts in each city a client serves. - Advertisers read
adsto see which sponsored products AI Mode shows next to the answer for your category. - GEO programs compare AI Mode citations with ChatGPT and Gemini citations for the same prompt set; see how AI engines choose citations.
Pitfalls
- Treating blocks as always present.
citationPills, product, place and video blocks are omitted when the answer has none. Store “absent” explicitly so it can be told apart from a failed run. - Mixing position bases. Shopping card positions start at 0; sources and inline products start at 1.
- Comparing runs across settings. A change in
hl,deviceorlocationchanges the answer. Keep the settings fixed per series and record them with every row. - Reading one run as the truth. Generated answers vary between runs. Judge trends over repeated runs; AI answer volatility covers how much sampling you need.
Field reference: AI Mode engine page.
Questions
Is there an official Google API for AI Mode answers?
Google does not publish an API that returns AI Mode answers as data. This API exposes AI Mode through POST /v1/monitor/aimode and the AIMODE async task type, returning the answer text, sources, citation pills, products, places, videos and ads as JSON.
What is the difference between AI Mode and AI Overview?
AI Overview is a generated summary shown above the normal results page, requested here with include.aioverview on a Google Search request. AI Mode is a separate conversational surface with its own answer, citations and product and place blocks, requested with the AIMODE task type.
How much does an AI Mode request cost?
An AI Mode request is $0.00206 ($2.06 per 1,000) on every tier, deducted from your prepaid balance.
Can I target a city with AI Mode requests?
Yes. Set country or gl for the market and add either location, in Google's canonical City,Region,Country form, or a pre-encoded uule. location and uule are mutually exclusive.
Which devices does the AI Mode endpoint support?
The device field accepts desktop, the default, or mobile.
Why are some AI Mode fields missing from a response?
Blocks such as citationPills, shoppingCards, places or videos only appear when the answer contains them, so treat every block as optional and store an empty value when it is absent.