Skip to main content
Lesson 8 of 12 · Structured JSON Outputs

Structured outputs and web search

Lesson 8 of 12 Updated July 28, 2026 Developer
On this page
  1. Combine structured outputs and real-time search
  2. Why this combination is powerful
  3. Prerequisites: Grok 4 minimum
  4. Example: Competitive intelligence
  5. Example: News tracking
  6. Best practices
  7. Key takeaways

Structured outputs aren’t just for static data. On Grok 4 and later models—meaning the entire current lineup—you can combine structured outputs with web search. The model searches the web for real-time information, then structures the results according to your schema.

Why this combination is powerful

Without this feature, getting structured data from the web requires three separate steps:

  1. Call a search API (Google, Bing, etc.)
  2. Parse the raw results
  3. Send the results to the LLM for structuring

With structured outputs + web search, everything happens in a single call. The model searches, synthesizes, and structures.

Prerequisites: Grok 4 minimum

This feature is available on Grok 4 and later models, which covers the entire current lineup (Grok 4.5, Grok 4.3, grok-4.20 variants). Older Grok 3 and Grok 3 Mini models did not support combining tools with structured outputs.

Example: Competitive intelligence

from pydantic import BaseModel

class Concurrent(BaseModel):
    nom: str
    site_web: str
    produit_phare: str
    avantage_principal: str

class VeilleConcurrentielle(BaseModel):
    secteur: str
    date_analyse: str
    concurrents: list[Concurrent]
    tendances: list[str]
    opportunites: list[str]

response, parsed = client.chat.parse(
    model="grok-4.20-0309-reasoning",
    messages=[{
        "role": "user",
        "content": "Perform competitive intelligence on the French neobank market in 2026"
    }],
    response_format=VeilleConcurrentielle,
    tools=[{"type": "web_search"}]
)

for c in parsed.concurrents:
    print(f"{c.nom} — {c.avantage_principal}")

The model will:

  1. Search for current French neobanks on the web
  2. Collect relevant information
  3. Structure everything according to the VeilleConcurrentielle schema

Example: News tracking

class Article(BaseModel):
    titre: str
    source: str
    date: str
    resume: str
    impact: str

class RevuePresse(BaseModel):
    sujet: str
    articles: list[Article]
    synthese: str

response, parsed = client.chat.parse(
    model="grok-4.20-0309-reasoning",
    messages=[{
        "role": "user",
        "content": "What is the latest news on AI regulation in Europe?"
    }],
    response_format=RevuePresse,
    tools=[{"type": "web_search"}]
)

print(parsed.synthese)
for article in parsed.articles:
    print(f"[{article.source}] {article.titre}")

Best practices

Be specific in the prompt

Web search works best with specific queries:

# Too vague
"What's new in tech?"

# Precise and actionable
"The 5 largest AI funding rounds in France in Q1 2026"

Adapt your schema to available data

Don’t request data the web cannot reliably provide:

# Hard to find precisely
class Entreprise(BaseModel):
    chiffre_affaires_exact: float  # rarely public

# Realistic
class Entreprise(BaseModel):
    chiffre_affaires_estime: str  # "around €50M"
    source_estimation: str

Handle missing data

Make fields optional if they might not be found:

class InfoEntreprise(BaseModel):
    nom: str
    fondateur: str
    annee_creation: int
    valorisation: str | None  # not always available
    nombre_employes: str | None

Key takeaways

  • The structured outputs + web search combination requires Grok 4 minimum—the entire current lineup is compatible
  • Enable web search with tools=[{"type": "web_search"}]
  • A single API call replaces a search → parsing → structuring chain
  • Be specific in your prompts for better results
  • Make fields optional if availability isn’t guaranteed