← All posts

Gemini Grounding with Google Search: How It Works and When to Bring Your Own Search

Gemini can search Google for you. Flip one switch in the API and the model decides when to run a web search, folds the results into its answer, and hands you citation metadata. No search API key, no scraping, no retrieval pipeline.

That convenience is real, and for a lot of apps it is the right default. But it comes with a per-request price, display obligations, and some hard limits on what you can do with the results. Let's walk through how the feature actually works, then look at where wiring up your own search tool wins.

How Grounding Works in the Gemini API

Grounding with Google Search is a built-in tool. You add it to the tools array and the model handles the rest: it decides whether the prompt needs fresh information, generates one or more search queries, reads the results, and writes an answer with the sources attached.

from google import genai
from google.genai import types

client = genai.Client(api_key="GEMINI_API_KEY")

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="What changed in the latest Node.js LTS release?",
    config=types.GenerateContentConfig(
        tools=[types.Tool(google_search=types.GoogleSearch())]
    ),
)

print(response.text)

The interesting part is what comes back alongside the text. Each grounded response carries a grounding_metadata object with three things you care about:

  • web_search_queries: the actual queries the model ran. Useful for debugging why an answer went sideways.
  • grounding_chunks: the sources, each with a title and a URI.
  • grounding_supports: mappings from spans of the answer text to the chunks that back them. This is what lets you render inline citations, footnote style.

One detail that surprises people: the URIs in grounding_chunks are not the real page URLs. They are redirect links through a Google domain (vertexaisearch.cloud.google.com/...). They resolve to the source when a user clicks them, but you cannot treat them as stable canonical URLs, and Google's terms limit how long you can retain them.

The Rules You Sign Up For

This is the part most tutorials skip. Grounding is not just a technical feature, it is a licensed use of Google Search results, and that license has conditions.

First, cost. At the time of writing, grounded requests are billed at $35 per 1,000 grounding-enabled prompts on top of normal token costs, with a free daily allowance (1,500 requests per day on paid tiers). If your app grounds every request and serves real traffic, that line item grows fast. Check Google's current pricing page before you commit, because the numbers and tiering have shifted between model generations.

Second, display requirements. When you show a grounded answer to users, Google requires you to display Search Suggestions, a rendered widget that comes back in the search_entry_point field as prebuilt HTML. You are expected to show it as-is, unmodified, adjacent to the response. If your UI is a terminal, a Slack bot, or a voice assistant, that requirement gets awkward.

Third, retention. You cannot cache or store the grounded results however you like. The terms restrict retaining search results and the redirect URIs beyond a limited window. That rules out the obvious optimization of grounding once and reusing the sources across users.

None of this is unreasonable. Google is selling access to its index with strings attached. You just want to know about the strings before you build.

What Grounding Gives You vs. What It Doesn't

The model reads search results, but you never see the full pages it read. You get snippets and citations, not documents. That matters more than it sounds.

If you are building anything that needs the underlying content, like a research tool that quotes sources at length, a pipeline that extracts structured data from pages, or a RAG system that chunks and embeds what it retrieves, grounding does not give you the raw material. It gives you an answer and pointers.

There is also the lock-in question. Grounding only exists inside Gemini. The moment you want the same app to run on Claude or GPT, or you want to A/B test models, your retrieval layer disappears with the model. A search tool you own moves with you.

When to Bring Your Own Search

Here is how I would split it:

Situation Built-in grounding Your own search tool
Quick factual freshness in a chat app Best fit Overkill
You need full page content, not snippets No Yes
Multi-model or model-agnostic architecture No Yes
Caching and storing retrieved data Restricted Your call
UI cannot render Search Suggestions widget Problematic Fine
Control over which sources get used Limited Full
Zero retrieval code, fastest ship Yes More work

Bringing your own search in Gemini means function calling. You declare a search_web function, the model calls it when it needs fresh data, and you return whatever your search layer produces. The wiring is maybe thirty lines:

search_tool = types.Tool(function_declarations=[{
    "name": "search_web",
    "description": "Search the web and return full page content",
    "parameters": {
        "type": "object",
        "properties": {"query": {"type": "string"}},
        "required": ["query"],
    },
}])

When the model calls it, you hit your search backend and feed the results into the next turn. The catch is what "your search backend" returns. A classic search API gives you titles and snippets, which puts you right back in snippet land, just with extra steps. To do better than grounding, your tool should return the actual content of the top results.

That is the gap link.sc was built for. Its /search endpoint returns ranked results with the full page content already extracted as markdown, so one call inside your search_web function gives Gemini complete documents to reason over, with real URLs you can cite, store, and reuse without a retention clock. I covered the full search-read-answer pattern in the real-time web search guide if you want the end-to-end version.

My Rule of Thumb

Use built-in grounding when the job is "make chat answers current" and you are committed to Gemini. It ships in an afternoon, the citation metadata is genuinely good, and the free daily allowance covers a lot of prototyping.

Switch to your own search tool the moment any of these become true: you need the pages themselves, you need to store what you retrieved, you run more than one model, or the Search Suggestions display requirement fights your UI. In my experience the second condition arrives sooner than people expect, because almost every serious LLM app eventually wants to do something with sources beyond linking to them.

Both paths are legitimate. Grounding is a product decision as much as a technical one: you are trading control and portability for speed. Just make that trade on purpose. And if you are giving an agent broader web access than a single search box, the agent internet access post covers the fetch side of the equation.


Want search results with full page content your model can actually read? Get 500 free credits a month at link.sc/register.