What Is Grounding?
One of the biggest weaknesses of LLMs is "hallucination" — generating responses that sound plausible but are factually incorrect or outdated. Grounding with Google Search addresses this by anchoring Gemini's responses in actual Google search results.
Basic Usage
import google.genai as genai
client = genai.Client(api_key="YOUR_API_KEY")
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="What are the latest AI industry trends in 2026?",
config={
"tools": [{"google_search": {}}]
}
)
print(response.text)With this simple configuration, Gemini automatically performs Google searches and generates responses based on the results.
Using Grounding Metadata
Source information is returned as grounding_metadata.
for candidate in response.candidates:
meta = candidate.grounding_metadata
if meta:
# Search queries used
for query in meta.web_search_queries:
print(f"Search query: {query}")
# Source information
for chunk in meta.grounding_chunks:
print(f"Title: {chunk.web.title}")
print(f"URL: {chunk.web.uri}")
# Grounding support details
for support in meta.grounding_supports:
print(f"Text: {support.segment.text}")Dynamic Retrieval
Not every request needs a search. Dynamic Retrieval lets Gemini automatically decide when searching is necessary.
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Explain the basic principles of quantum computing",
config={
"tools": [{
"google_search": {
"dynamic_retrieval_config": {
"mode": "MODE_DYNAMIC",
"dynamic_threshold": 0.5
}
}
}]
}
)Adjust dynamic_threshold to control search sensitivity:
- 0.0: Always search
- 0.5: Balanced threshold (recommended default)
- 1.0: Rarely search
Comparison with Custom RAG
| Aspect | Grounding with Google Search | Custom RAG |
|---|---|---|
| Data source | Google search index | Your own database |
| Setup | Zero (API parameter only) | Requires vector DB |
| Freshness | Real-time | Depends on update frequency |
| Cost | Per API usage | Infrastructure + API costs |
| Customization | Low | High |
| Internal data | Not available | Supported |
Implementation Patterns
News Summary Bot
def get_news_summary(topic: str) -> str:
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=f"Summarize the 3 latest news items about {topic}. Include source URLs.",
config={
"tools": [{"google_search": {}}]
}
)
return response.textFact Checker
def fact_check(claim: str) -> str:
response = client.models.generate_content(
model="gemini-2.5-pro",
contents=f"Fact-check the following claim using search results. Provide verdict and evidence.\n\nClaim: {claim}",
config={
"tools": [{"google_search": {}}]
}
)
return response.textCost Management
Grounding with Google Search is powerful but incurs additional cost per request.
Optimization tips:
- Use Dynamic Retrieval to avoid unnecessary searches
- Disable grounding for creative tasks that don't need fact-checking
- For batch processing, generate answers without search first, then apply grounding only to low-confidence sections
Limitations
- Search results depend on Google's search index — unindexed information cannot be retrieved
- Internal or private data is inaccessible (use custom RAG for those cases)
- Search result language is influenced by the prompt language
Common Pitfalls and Things to Watch For
Grounding is easy to enable, but in production you run into subtle issues — searches that never fire, citations that drift, display requirements you didn't know about. Wiring this into my own projects as an indie developer, I lost time to a few of these before I understood what was happening. Here are the ones worth knowing before you ship.
grounding_metadata comes back empty
When no source information is returned, check web_search_queries first. If it's empty, no search ran at all.
Gemini skips the search when it decides its internal knowledge is enough, or when the prompt has no time-sensitive angle. To force a fresh lookup, anchor the prompt in time — "the latest," "as of June 2026" — so the model leans toward searching.
dynamic_threshold has no effect
dynamic_retrieval_config and dynamic_threshold belong to the google_search_retrieval tool on Gemini 1.5 models. On the Gemini 2.5 google_search tool they're ignored, and the model decides whether to search on its own.
If changing the threshold on a 2.5 model seems to do nothing, this mismatch is why. On 2.5, just pass {"google_search": {}}.
Citation offsets drift (especially for multibyte text)
The start_index / end_index in grounding_supports.segment are UTF-8 byte offsets. Python strings are indexed by character, not byte, so slicing response.text directly misaligns citations for Japanese and other multibyte text.
Encode to bytes first, slice, then decode:
raw = response.text.encode("utf-8")
for support in meta.grounding_supports:
seg = support.segment
cited = raw[seg.start_index:seg.end_index].decode("utf-8")
sources = [meta.grounding_chunks[i].web.uri
for i in support.grounding_chunk_indices]
print(cited, "→", sources)Search Suggestions are required
When you display a grounded response, Google's terms require you to show the Search Suggestions. The ready-to-use HTML lives in grounding_metadata.search_entry_point.rendered_content — embed it near the answer. Omitting it may violate the terms of use.
Searches run but return stale or wrong facts
If the search fires but the content is outdated, pin the time period in the prompt and lower temperature to keep the model faithful to the retrieved results.
When fact-checking is the goal, use gemini-2.5-pro instead of gemini-2.5-flash and state explicitly that it should not infer beyond what the search results say.
Looking back
Grounding with Google Search dramatically improves the accuracy of Gemini's responses. It's essential for use cases where up-to-date information and fact-checking matter. Combined with Dynamic Retrieval, you can optimize the balance between cost and accuracy.