GEMINI LABJP
SUNSET — The image generation models shut down tomorrow, August 17: imagen-4.0-generate-001, ultra, fast, and the Gemini 3 Image family, and calls will fail with a hard errorGA — Gemini 3.7 Flash reached general availability on August 13, with substantial gains in software engineering, web development, and agentic work at an introductory price through December 31APPS — On August 12 Google widened the set of apps you can connect to Gemini, adding Granola, Otter.ai, and Wix alongside OpenTable, Ticketmaster, iHeartRadio, and PandoraSAMPLING — The temperature, top_p, and top_k sampling parameters are now deprecated, so migrating to a newer model means revisiting those assumptionsROBOTICS — Gemini Robotics ER 2 is in public preview, and the older gemini-robotics-er-1.6-preview shuts down on August 31NOTEBOOK — NotebookLM Enterprise has been renamed Gemini Notebook Enterprise, and the Gemini Enterprise mobile app is now generally availableSUNSET — The image generation models shut down tomorrow, August 17: imagen-4.0-generate-001, ultra, fast, and the Gemini 3 Image family, and calls will fail with a hard errorGA — Gemini 3.7 Flash reached general availability on August 13, with substantial gains in software engineering, web development, and agentic work at an introductory price through December 31APPS — On August 12 Google widened the set of apps you can connect to Gemini, adding Granola, Otter.ai, and Wix alongside OpenTable, Ticketmaster, iHeartRadio, and PandoraSAMPLING — The temperature, top_p, and top_k sampling parameters are now deprecated, so migrating to a newer model means revisiting those assumptionsROBOTICS — Gemini Robotics ER 2 is in public preview, and the older gemini-robotics-er-1.6-preview shuts down on August 31NOTEBOOK — NotebookLM Enterprise has been renamed Gemini Notebook Enterprise, and the Gemini Enterprise mobile app is now generally available
Articles/Dev Tools
Dev Tools/2026-07-02Advanced

url_context Still Answers When the Fetch Fails — Gating on Retrieval Status Before You Trust It

The url_context tool returns a confident answer even when it failed to fetch the target page. This walks through reading url_retrieval_status from url_context_metadata to build a verification gate, plus a fallback that only finalizes an answer when the source URL was truly read.

Gemini API210url_contextgrounding8automation52reliability7

Premium Article

The scariest moment I had with url_context in automation was when the fetch of a target page had failed, yet the response came back looking perfectly normal. As an indie developer running the several sites of Dolice Labs, I run a periodic job that drafts material across them, and one small step points Gemini at an official changelog page via url_context and asks it to pull out the key points. One morning, part of a generated draft described things that were nowhere on the actual page — plausible, but invented.

Tracing it back, the URL retrieval had failed. But the response was not empty: the model had filled in from its own knowledge and returned it as if it had read the page. My implementation never checked whether the fetch succeeded, so that difference was completely invisible to me.

Treat url_context retrieval as best-effort

url_context is a tool that lets the model fetch the URLs you name and use them as grounding material. The easy thing to miss is that a failed fetch does not turn the call into an error. A transient network failure, a robots block, a page that renders almost empty client-side, a size limit — there are many reasons a retrieval can come up short. In most of those cases the response still returns 200, and the body still reads convincingly.

In automation, this silent failure is the dangerous part. A person watching the screen would notice "wait, this looks stale." But a scheduled job passes the returned text straight to the next step. Unless you check the primary signal — whether the fetch actually succeeded — empty answers keep leaking into your content.

Read url_context_metadata first

The saving grace is that the retrieval outcome comes back as metadata. Each candidate carries url_context_metadata, and inside it url_metadata lists the URLs the model tried to fetch along with a retrieval status. Read that, and you can decide mechanically which URLs were genuinely read.

Start by pulling just the retrieval status out of the response.

from google import genai
from google.genai import types
 
client = genai.Client()
 
def ask_with_url_context(prompt: str, urls: list[str]):
    # Including the URLs in the prompt lets url_context attempt to fetch them
    url_list = "\n".join(urls)
    full_prompt = f"{prompt}\n\nURLs to consult:\n{url_list}"
 
    resp = client.models.generate_content(
        model="gemini-flash-latest",
        contents=full_prompt,
        config=types.GenerateContentConfig(
            tools=[types.Tool(url_context=types.UrlContext())],
        ),
    )
    return resp
 
def extract_retrievals(resp) -> list[dict]:
    """Return each URL's retrieval outcome as [{url, status}]."""
    out = []
    for cand in resp.candidates or []:
        meta = getattr(cand, "url_context_metadata", None)
        if not meta:
            continue
        for um in getattr(meta, "url_metadata", []) or []:
            out.append({
                "url": getattr(um, "retrieved_url", None),
                "status": str(getattr(um, "url_retrieval_status", "")),
            })
    return out

url_retrieval_status comes back as an enum. Success ends in SUCCESS, a failed fetch ends in ERROR, and a value containing UNSAFE means it was excluded for safety reasons. Stringifying it and matching on the suffix keeps you from being tripped up by small SDK type differences.

Status (suffix)MeaningHow to treat that answer
SUCCESSThe URL was fetchedAccept as grounding
ERRORThe fetch failedDo not accept — go to fallback
UNSAFEExcluded for safetyDo not accept — send to human queue
(no metadata)No fetch was even attemptedFail as ungrounded

The trickiest row is the last one: empty metadata. Even when you think you put the URL in the prompt, the model may not attempt a fetch and answer from internal knowledge alone. "No record of retrieval" is easy to mistake for success, so reject it explicitly rather than letting it through.

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
A verification gate that reads url_retrieval_status from url_context_metadata and rejects any answer grounded on a URL that failed to fetch
A two-stage fallback that switches to an explicit fetch on failure and finalizes an answer only when the source was actually read
An idempotent apply pattern that stops confident-but-empty answers from quietly leaking into automated content
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

Dev Tools2026-06-20
Routing Gemini by Pipeline Stage: Draft on Flash, Finish on the Top Tier
A record of reworking which Gemini model handles which stage of an automation pipeline, prompted by the general availability of Gemini 3.5 Flash and the rollout of 3.1 Flash-Lite. Includes a small router that splits work into draft, classify, and finalize stages, how the cost picture changes, and the guardrails I settled on.
Dev Tools2026-08-05
Green Tests, Dead Production — How Recorded Fixtures Hide a Model Retirement, and a Freshness Gate to Catch It
A test suite that replays recorded API responses will sail straight past a model retirement. I reproduce the failure in a minimal setup and build a cassette freshness gate, with measured overhead.
Dev Tools2026-07-25
The Day I Stopped Tracking gemini-flash-latest: Batch Design That Survives Silent Model Swaps
A silent model swap pushed my batch rejection rate from 2.1% to 9.8% overnight. The pinning-plus-canary design I moved to, with the harness and numbers.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →