Repository navigation
Commands
Two commands, check and read. Outputs below come from fetchwright 0.1.0 run against a stand-in for Google's API, with sample content (see Home).
python fetchwright.py --helpusage: fetchwright [-h] [--version] {check,read} ...
Read pages other fetchers cannot, through Gemini's URL context tool.
positional arguments:
{check,read}
check is a key set, and which models answer (one tiny request per
model)
read read one or more public pages
options:
-h, --help show this help message and exit
--version show program's version number and exit
python fetchwright.py --versionfetchwright 0.1.0
python fetchwright.py check --helpusage: fetchwright check [-h] [--models MODELS] [--no-call]
[--timeout TIMEOUT] [--json]
options:
-h, --help show this help message and exit
--models MODELS comma-separated, first is tried first (default
gemini-3.8-flash,gemini-3.5-flash-lite or
FETCHWRIGHT_MODELS)
--no-call only look for the key; send nothing
--timeout TIMEOUT
--json
- Without
--no-callit sends one request per model ("Reply with the word OK.", no URL tool) and reports which answer. It stops early on a refused key or a 429. -
--timeoutdefaults to 90 seconds forcheck. - Exit 0 when a key is found and, with calls, at least one model answers. Exit 4 with no key, or when every model refused the key. Exit 5 when every model was unavailable.
With no key set:
python fetchwright.py check --no-callfetchwright 0.1.0
key: not set (GEMINI_API_KEY)
That exits 4. With a key, see Getting started.
python fetchwright.py read --helpusage: fetchwright read [-h] [--thread | --page] [--verbatim | --digest]
[--max-comments MAX_COMMENTS] [--models MODELS]
[--timeout TIMEOUT] [--gap GAP] [--json] [--out OUT]
[--max-chars MAX_CHARS] [--save-raw DIR]
URL [URL ...]
positional arguments:
URL
options:
-h, --help show this help message and exit
--thread read as a discussion thread: title, post, comments
--page read as a page: title and main text
--verbatim ask for the text word for word (threads do by default;
long pages are often blocked as recitation, then
fetchwright retries as a digest)
--digest ask for a faithful account instead of quotes (pages do
by default)
--max-comments MAX_COMMENTS
ask for at most N comments (cuts output tokens)
--models MODELS comma-separated model list; the next is tried on 5xx,
404 or a dropped connection
--timeout TIMEOUT seconds per request (default 120)
--gap GAP seconds between URLs (default 5)
--json
--out OUT write the output to this file instead of stdout
--max-chars MAX_CHARS
cut stdout here (0 for no limit)
--save-raw DIR keep each raw response here (page text: keep it out of
repositories)
| option | what it does |
|---|---|
--thread, --page
|
Force the shape. Without either, a reddit.com/.../comments/... URL or a Hacker News item URL reads as a thread, anything else as a page. |
--verbatim, --digest
|
Word for word, or a faithful account. Threads default to word for word, pages to a digest. See How pages are read. |
--max-comments N |
Asks the model for at most N comments. Fewer comments means fewer output tokens, which are most of the cost of a thread. |
--models a,b |
The model list, tried in order. Default gemini-3.8-flash,gemini-3.5-flash-lite, or FETCHWRIGHT_MODELS. |
--timeout S |
Seconds per request, default 120. |
--gap S |
Seconds between URLs, default 5. One request per URL. |
--json |
One JSON record per URL (a list when there are several). The fields are on How pages are read. |
--out FILE |
Write everything to FILE (UTF-8, LF) and print one line saying so. Not cut. |
--max-chars N |
Cut what goes to stdout at N characters, default 25,000; 0 for no limit. |
--save-raw DIR |
Keep each raw API response as JSON in DIR. They hold page text: keep them out of repositories. |
The 25,000-character cut applies to --json on stdout too, so a long thread printed as JSON can end mid-record and fail to parse. For JSON a program reads, use --out FILE or --max-chars 0:
python fetchwright.py read https://www.reddit.com/r/examplesub/comments/1abc234/ --json --max-chars 900ends with:
[cut at 900 characters of 1357; use --max-chars 0 or --json --out FILE]
python fetchwright.py read https://example.org/articleWhen Google could not retrieve the page:
# https://example.org/article
url: https://example.org/article
model: gemini-3.8-flash mode: page style: digest (the model's account, not quotes)
retrieval: error https://example.org/article
tokens: page 300, output 410, total 900
NOT READ: Not able to browse the provided URL.
The style line names the style that was asked for, even when nothing was read.
The page text, check's report and the wrote FILE line go to stdout. Errors that end the run go to stderr:
python fetchwright.py read https://www.reddit.com/r/examplesub/comments/1abc234/with no key set:
No Gemini API key: set GEMINI_API_KEY (the fetchwright-setup skill walks through it).
On a 429 that names one model's own quota (Google's message says "per day" or "for model"), fetchwright moves to the next model and skips the spent one for the rest of the run (since 0.2.0). Any other 429, or a quota 429 when every model's quota is spent, stops the run at once, even with more URLs to go, and prints the records it already has:
rate limited (429): Resource has been exhausted. Stopped: wait before trying again, and check the quota in AI Studio.
A URL that is not http or https:
python fetchwright.py read file:///etc/hostsnot an http(s) URL: file:///etc/hosts
| code | meaning |
|---|---|
| 0 | every URL was read |
| 1 | at least one page was not read (the record says why) |
| 2 | bad arguments, or a URL that is not http or https |
| 3 | rate limited (HTTP 429), or every model's daily quota spent: the run stopped |
| 4 | no key, the key was refused (400 "API key not valid", 401, 403), or payment needed (402) |
| 5 | every model was unavailable (5xx, 404 or a dropped connection) |
| variable | used for |
|---|---|
GEMINI_API_KEY |
the key (preferred) |
GOOGLE_API_KEY |
the key, when GEMINI_API_KEY is not set |
FETCHWRIGHT_MODELS |
the default model list, comma-separated |
On Windows, when neither key variable is in the environment, fetchwright reads them from the user environment in the registry (HKCU\Environment). That finds a key set with setx after the shell started.
fetchwright writes no files of its own: only --out and --save-raw write, and only where you say.
This wiki describes fetchwright 0.2.0 and was last updated on 2026-10-16. fetchwright is MIT licensed. Report problems in the issues. Releases: GitHub releases.
Using it
The releases
Contributing
Elsewhere