Skip to content

How Pages Are Read

Mark Rogers edited this page Oct 16, 2026 · 2 revisions

What happens between the URL you give and the record you get back. Outputs come from fetchwright 0.1.0 against a stand-in for Google's API, with sample content (see Home).

The request

One request per URL, to Gemini's Interactions API (POST /v1beta/interactions), with:

  • the model name;
  • an instruction that names the URL and asks for JSON;
  • the URL context tool, and no other tool;
  • store: false, so Google does not keep the exchange (by default it would, 1 day on the free tier and 55 days on paid, per the docs on 2026-10-15).

The code refuses to build a request with Google Search in it, in any spelling. Google's terms restrict what may be done with Search results, so fetchwright never asks for them (Terms and privacy).

URL context tries Google's index first, then a live fetch. That is why a Reddit thread reads even though Reddit refuses scripts: Google already holds a copy. A thread too new to be in the index does not read. One 8.6 hours old was indexed on 2026-10-15; nothing younger was tried.

Threads and pages

A Reddit /comments/ URL or a Hacker News item URL is read as a thread: title, post body, and comments, word for word, in page order, with the poster's own replies marked [OP]. Any other URL is read as a page: title and main content.

Pages default to a digest: a faithful section-by-section account in the page's order, with names, numbers, dates and links kept exactly and at most a sentence quoted at a time. The reason: on 2026-10-15, asking for a whole Wikipedia article word for word got HTTP 400 "Request blocked due to copyright/recitation content", and the digest read every section. Thread comments are short and copied fine.

python fetchwright.py read https://example.org/article
# An example article
url: https://example.org/article
model: gemini-3.8-flash  mode: page  style: digest  (the model's account, not quotes)
retrieval: success https://example.org/article
tokens: page 3120, output 410, total 3720

The article opens with what the project is for.

Its second section lists three releases, in 2024, 2025 and 2026.

A digest is the model's account, never a quote. --verbatim asks for the exact text. When Google blocks it as recitation, fetchwright asks once more for a digest, and the record says style: digest with both attempts in models_tried:

python fetchwright.py read https://example.org/article --verbatim --json
{
 "fetchwright": "0.1.0",
 "url": "https://example.org/article",
 "mode": "page",
 "style": "digest",
 ...

The retrieval check

Each response carries Google's retrieval status for every URL it touched, and fetchwright prints them all (retrieval: in text, retrieval in JSON).

  • Statuses seen on 2026-10-15: success and error. The docs also name paywall and unsafe. Any other value is listed under new_statuses ("new retrieval status seen").
  • A Reddit thread comes back with two entries: the thread's full slug URL with success, which is the index copy, and the bare URL you gave with error, because Reddit refused the live fetch. That is normal.
  • If no URL shows success, fetchwright throws away whatever the model wrote and reports the page as not read, even when the model claimed it was. A model can answer from memory, and this rule keeps that out.

What gets dropped

From threads, before anything is printed:

  • Placeholders. "Comment removed by moderator", "Comment removed by Reddit", "Comment deleted by user", [deleted], [removed], and the "Comment Image" marker are dropped. When a placeholder starts a comment and real text follows it, the placeholder goes and the text stays. A post body that is only a placeholder is reported as removed (body_removed).
  • Lone usernames. Gemini sometimes returns a commenter's username as the comment's text: 20 times in 381 comments in a test on 2026-10-15. Any comment that is a single token of username shape (3 to 24 letters, digits, _ or -, optionally after u/) is dropped. A one-word comment such as "lol" goes too, because it cannot be told apart from a username, and one word gives a note nothing to use.
  • Empty comments.

The counts are in the comments heading in text and in dropped in JSON. In the sample on Home, "Example_User_1234" and "Comment removed by moderator" were dropped.

Deleted posts and comments came back as placeholders or empty in every test, never as their old text.

Models and fallback

The default list is gemini-3.8-flash, then gemini-3.5-flash-lite. The next model is tried when one answers 5xx, 404 (model gone or closed to new keys), a 400 that is not about the key, or drops the connection. A 429 that names one model's own quota moves to the next model, and the spent model is skipped for the rest of the run (since 0.2.0). Any other 429, a quota 429 when every model is spent, or a 401, 402, 403 or "API key not valid" stops the whole run.

python fetchwright.py read https://www.reddit.com/r/examplesub/comments/1abc234/ --json --max-chars 900

with the first model overloaded, begins:

{
 "fetchwright": "0.1.0",
 "url": "https://www.reddit.com/r/examplesub/comments/1abc234/",
 "mode": "thread",
 "style": "verbatim",
 "model": "gemini-3.5-flash-lite",
 "models_tried": [
  {
   "model": "gemini-3.8-flash",
   "http": 503,
   "seconds": 0.1,
   "outcome": "next",
   "why": "overloaded (503): This model is currently experiencing high demand."
  },

On 2026-10-15 that was the usual case: gemini-3.8-flash answered check but returned 503 or dropped the connection on URL context reads, and gemini-3.5-flash-lite read every page.

The JSON record

python fetchwright.py read https://www.reddit.com/r/examplesub/comments/1abc234/ --json
{
 "fetchwright": "0.1.0",
 "url": "https://www.reddit.com/r/examplesub/comments/1abc234/",
 "mode": "thread",
 "style": "verbatim",
 "model": "gemini-3.8-flash",
 "models_tried": [
  {
   "model": "gemini-3.8-flash",
   "http": 200,
   "seconds": 0.1,
   "outcome": "ok",
   "why": ""
  }
 ],
 "read_ok": true,
 "why_not": "",
 "retrieval": [
  {
   "url": "https://www.reddit.com/r/examplesub/comments/1abc234/a_small_upscaler_node/",
   "status": "success"
  },
  {
   "url": "https://www.reddit.com/r/examplesub/comments/1abc234/",
   "status": "error"
  }
 ],
 "new_statuses": [],
 "title": "I made a small upscaler node",
 "usage": {
  "input": 190,
  "page": 4210,
  "output": 410,
  "total": 4810
 },
 "body": "It upscales video in tiles so it fits in 8 GB.\n\nLink in the comments.",
 "body_removed": false,
 "comments": [
  {
   "text": "Works on my 3060, about 2 fps at 1080p.",
   "author_is_op": false
  },
  {
   "text": "Thanks for testing. Tiles of 512 are the default.",
   "author_is_op": true
  },
  {
   "text": "Does it keep the audio track?",
   "author_is_op": false
  }
 ],
 "dropped": {
  "placeholder": 1,
  "lone_token": 1,
  "empty": 0
 }
}
field meaning
mode, style thread or page; verbatim or digest (the style finally used)
model, models_tried the model that answered, and every attempt with its HTTP status, seconds, outcome and reason
read_ok, why_not whether the page was read, and why not
retrieval, new_statuses Google's status per URL; statuses the docs do not list
usage tokens: your instruction (input), the fetched page (page), the answer (output), total
body, body_removed, comments, dropped threads only
text pages only
unparsed only when the model's answer was not JSON: its first 2,000 characters

No usernames appear anywhere in the record.

How much comes back

In a test on 2026-10-15 with six real Reddit threads on gemini-3.5-flash-lite, titles and post bodies were right six of six. Comments returned: 20 of 21, 47 of 51, 12 of 13, 151 of 185, 62 of 174 and 89 of 251. Long threads come back in part. Strikethrough is lost, so a struck-out claim reads as asserted. Each thread cost 3,000 to 15,000 page tokens plus 600 to 10,000 output tokens. No comment was shown to be invented.

Clone this wiki locally