◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/API / SDK
◈ API / SDK/2026-06-20Advanced

Gemini API Grounding × Structured Output Guide — Turn Web Search Results into Typed JSON Data

Combine Gemini API Grounding with Google Search and Structured Output to extract real-time web information as type-safe JSON data. Practical implementation patterns included.

Gemini API249Grounding4Structured Output11Google Search3JSONreal-time dataagents9

✦ Premium Article

You want the Gemini API to fetch external information and return it as structured data. Until recently, you couldn't do both at the same time. Enabling Grounding with Google Search blocked Structured Output, and vice versa. The Gemini 3 API update finally removed this restriction.

Getting web search results back as JSON that matches your type definitions — this combination means you can now handle tasks like "fetch current exchange rates and return them as a JSON array" or "search competitor product prices and format them for a comparison table" in a single API call.

The Problem This Combination Solves

The old approach required a two-stage pipeline.

First API call: use Grounding to fetch web information, receive a text response. Second API call: feed that text into Structured Output to get JSON. Double the cost, double the latency, and a real risk of information loss when re-feeding the text response.

The unified API lets you specify Google Search in tools while defining a JSON schema via response_mime_type. The model executes the search, interprets the results, and converts everything into your specified type — all in one step.

from google import genai
from google.genai import types
import json
 
client = genai.Client()
 
# Combined Grounding + Structured Output request
response = client.models.generate_content(
    model="gemini-2.5-pro",
    contents="Look up the current Gemini API pricing as of April 2026, organized by model",
    config=types.GenerateContentConfig(
        tools=[types.Tool(google_search=types.GoogleSearch())],
        response_mime_type="application/json",
        response_schema={
            "type": "object",
            "properties": {
                "pricing_data": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "model_name": {"type": "string"},
                            "input_price_per_million": {"type": "string"},
                            "output_price_per_million": {"type": "string"},
                            "context_window": {"type": "string"},
                        },
                        "required": [
                            "model_name",
                            "input_price_per_million",
                            "output_price_per_million"
                        ]
                    }
                },
                "last_updated": {"type": "string"},
                "source_urls": {
                    "type": "array",
                    "items": {"type": "string"}
                }
            },
            "required": ["pricing_data", "last_updated"]
        }
    )
)
 
# Type-safe JSON returned directly
data = json.loads(response.text)
for model in data["pricing_data"]:
    print(f"{model['model_name']}: input {model['input_price_per_million']}/1M tokens")
 
# Verify sources via grounding metadata
if response.candidates[0].grounding_metadata:
    for chunk in response.candidates[0].grounding_metadata.grounding_chunks:
        print(f"  Source: {chunk.web.title} — {chunk.web.uri}")

What you get back is structured JSON derived from live Google Search results. No fields outside your schema, no missing required fields.

Understanding the Response Structure

The combined response includes your Structured Output JSON plus grounding_metadata. This metadata contains the search queries used, source URLs, and citation information.

candidate = response.candidates[0]
 
# 1. Structured JSON text
structured_data = json.loads(candidate.content.parts[0].text)
 
# 2. Grounding metadata
metadata = candidate.grounding_metadata
 
# Queries the model used for searching
print("Search queries:", metadata.web_search_queries)
# → ['Gemini API pricing 2026', 'Gemini 2.5 Pro API cost per token']
 
# Source web pages
for chunk in metadata.grounding_chunks:
    print(f"Source: {chunk.web.title}")
    print(f"  URL: {chunk.web.uri}")
 
# Citation supports (which parts of the response are backed by which sources)
for support in metadata.grounding_supports:
    print(f"Text: {support.segment.text}")
    print(f"  Source indices: {support.grounding_chunk_indices}")
    print(f"  Confidence: {support.confidence_scores}")

One thing to watch out for: when combined with Structured Output, the text response is in JSON format, so grounding_supports segment.text may point to JSON fragments rather than readable sentences. For source verification, the grounding_chunks URL list is more reliable.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Combine Grounding and Structured Output in a single call to extract web search results as type-safe JSON
✦A working verification gate that quarantines records by checking grounding_metadata provenance, with threshold design
✦End-to-end production know-how: schema design, cost structure, and the gotchas that bite real extraction pipelines
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◈ API / SDK2026-06-12
Building an App Store Rejection Workflow with the Gemini API — From Structured Notices to Resolution Center Replies
How I use the Gemini API to parse App Store rejection notices into structured JSON, cross-check guidelines, draft Resolution Center replies, and run pre-submission checks as an indie developer.
◈ API / SDK2026-05-21
When responseSchema enum returns unexpected values — debugging Gemini API
Why Gemini API sometimes returns values outside the enum you defined in responseSchema, and the three-layer workaround I use in production for my wallpaper app classification pipeline.
◈ API / SDK2026-10-14
When Your config Raises "Extra inputs are not permitted", Check the Spelling of Every Key
If a google-genai call fails with a pydantic ValidationError (extra_forbidden) the moment you pass a config, it is almost always a one-letter typo. Here is the output I reproduced, a small function that checks keys before the call, and how to tell why response.text came back as None.