Grounding With Google Search in the Gemini API
9 min read · updated August 11, 2026
Search grounding is declared as a tool with an empty configuration object, and it is not a function call: the model does not hand you a request to execute. Google runs the search, uses the results, and returns provenance in a groundingMetadata block alongside the answer.
The tool declaration
For Gemini 2.0 and later, per Google’s Search grounding documentation, the tool is named google_search and takes no configuration:
{
"contents": [
{ "role": "user", "parts": [{ "text": "Who won the 2026 Six Nations and by what points difference?" }] }
],
"tools": [
{ "google_search": {} }
]
}The 1.5 generation used a different tool, google_search_retrieval, which carried a dynamic_retrieval_config with a mode of MODE_DYNAMIC and a dynamic_threshold between 0 and 1—a knob for how confident the model had to be that a query needed searching before a search was run. That configurability was removed in the newer tool; with google_search the decision to search is the model’s. If you are reading an example with a threshold in it, it is written for 1.5.
Because it is a tool rather than a mode, grounding coexists with your own function declarations in the same tools array, and tool_config modes apply to your functions in the usual way. What it does not coexist with is structured output: a request that asks for response_mime_type: "application/json" with a schema and also declares Search is rejected in current versions, which forces a two-call design if you need grounded facts in a fixed shape.
groundingMetadata, field by field
When a search actually ran, the candidate carries an extra sibling of content:
{
"candidates": [
{
"content": { "role": "model", "parts": [{ "text": "..." }] },
"finishReason": "STOP",
"groundingMetadata": {
"webSearchQueries": ["2026 six nations winner points difference"],
"searchEntryPoint": {
"renderedContent": "<style>...</style><div class=\"container\">...</div>"
},
"groundingChunks": [
{ "web": { "uri": "https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbC...", "title": "sixnationsrugby.com" } },
{ "web": { "uri": "https://vertexaisearch.cloud.google.com/grounding-api-redirect/DeF...", "title": "bbc.co.uk" } }
],
"groundingSupports": [
{
"segment": { "startIndex": 0, "endIndex": 58, "text": "..." },
"groundingChunkIndices": [0],
"confidenceScores": [0.94]
}
]
}
}
]
}The absence of this block is meaningful. A model with google_search declared may answer from its own weights without searching, in which case there is no groundingMetadata and the answer carries no provenance at all. “Grounding is on” and “this answer is grounded” are different claims, and only the second is checkable—by the presence of the field.
The URIs in groundingChunks are redirect links on vertexaisearch.cloud.google.com rather than the publishers’ own URLs. They resolve to the source, and they expire. If your product stores citations for later display, store the title and resolve or record the destination at the time of the response; a redirect URI persisted into a database will stop working.
Mapping citations onto the answer
groundingSupports is the part that makes inline citations possible, and it takes a moment to read correctly. Each entry says: the span of the answer text between segment.startIndex and segment.endIndex is supported by the sources at these positions in groundingChunks.
- Take the answer text from
candidates[0].content.partsand concatenate the parts into one string. - For each
groundingSupport, slice that string usingsegment.startIndexandsegment.endIndex. These are byte offsets into the UTF-8 encoding, so in a language whose strings are UTF-16 or a sequence of code points—JavaScript, Python—you must encode to bytes, slice, and decode back, or your markers will drift the moment the answer contains a non-ASCII character. - Look up each index in
groundingChunkIndicesagainstgroundingChunksto get the source title and URI. - Insert markers working from the end of the string backwards, so that earlier offsets remain valid while you mutate.
confidenceScores is parallel to groundingChunkIndices: one score per cited chunk, for that segment. It is a useful filter for suppressing weak citations, and not a measure of whether the claim is true.
The display requirement
searchEntryPoint.renderedContent is a block of HTML and CSS containing Google Search Suggestions—the chips showing the queries that were run. Google’s grounding documentation requires that applications display it, unmodified, whenever grounded results are shown. It is not optional decoration and it is not something to restyle.
Practically: render it in a container that does not fight its own CSS, and note that it arrives as a string of HTML, so a framework that escapes by default needs an explicit raw-HTML insertion for it.
When the model searches, and when it does not
Declaring the tool grants permission; it does not compel a search. With the 1.5-era google_search_retrieval tool you could bias this decision numerically through dynamic_threshold. With google_search you cannot, so the only levers left are the prompt and the shape of the question.
The model is more likely to search when the question is answerable only with current information and the prompt makes that explicit. It is less likely to search when the question looks like general knowledge it already has, which is exactly the case where a stale answer is most plausible and hardest to notice. Three things help:
- Name the recency requirement. “As of today, what is...” and “according to current published information” are more likely to trigger a search than the same question asked flatly.
- Ask for sources in the answer. A request to cite where each claim came from aligns the model’s output with the behaviour that produces citations.
- Check, do not assume. The reliable move is not to coax but to verify: if
groundingMetadatais absent and your use case requires grounding, treat the response as unusable and say so, rather than serving an ungrounded answer through a grounded interface.
webSearchQueries is worth reading as a debugging tool in its own right. It contains the queries the model actually issued, and when a grounded answer is wrong it is very often because the query was wrong — too broad, missing a qualifier from your prompt, or resolving an ambiguous name to the wrong entity. That is fixable by rewriting the prompt to disambiguate, and it is invisible unless you log the field.
One structural note: grounding is decided per turn, not per conversation. In a multi-turn exchange, an earlier turn that searched leaves its answer in the history, and a later turn may reason from that stored text rather than searching again. The results your conversation is standing on can therefore be minutes or hours old with nothing in the latest response indicating it.
What grounding does not do
- It does not guarantee the answer is supported. Segments outside any
groundingSupportare ungrounded text in a grounded response. If accuracy matters, treat unsupported spans differently in your interface rather than presenting the whole answer as cited. - It is not a web-scraping tool. You get search results as the model used them; you do not get page contents, and you cannot direct it at a specific site through the API.
- It is billed separately. Grounded requests carry a per-request charge on top of tokens, so a grounding tool left declared on every call in a chat application is a cost line of its own. Declare it on the turns that need it.
- It adds latency. A search round trip happens inside your request. Time-to-first-token on a grounded call is not comparable to an ungrounded one.