Skip to content
rewget GitHub

v1.0.1 · Linux + macOS

wget, but it works everywhere.

A drop-in wget replacement that automatically bypasses bot protection. When sites return 403, hand you a CAPTCHA, or just refuse to talk to a plain HTTP client, rewget retries with browser-grade fingerprints and, if it has to, a real headless browser.

$ brew install neul-labs/tap/rewget
$ rewget https://example.com/file.tar.gz
--2026-06-05 10:14:02--  https://example.com/file.tar.gz
file.tar.gz                100%[============>]   42.1M  18.6MB/s
[stage 1: wget] ok

3

stages of fallback: wget, fingerprint, browser

7 d

per-domain cache so the slow path runs once

6

signed browser profiles: Chrome, Firefox, Safari, Edge

What is rewget?

A wget that gets through

rewget is a drop-in wget replacement written in Rust. It keeps the wget command-line surface exactly as it is and adds a three-stage fallback: plain wget first, browser-impersonating HTTP second, a real headless browser third. When a site blocks a plain HTTP client with a 403, a CAPTCHA, or a rate limit, rewget quietly retries with something the site will accept.

On sites that never block, you pay nothing — you get wget, byte for byte. rewget also caches which stage works per domain for seven days, so repeated jobs against the same host skip straight to the answer.

plain wget — blocked
$ wget https://protected.example/dataset.zip
HTTP request sent, awaiting response... 403 Forbidden
ERROR 403: Forbidden.
same URL — rewget
$ rewget https://protected.example/dataset.zip
[stage 1: wget] 403 → escalating
[stage 2: rquest/chrome131] 200 OK
dataset.zip            100%[============>]  128M  22.4MB/s

How it works

A three-stage fallback that stays out of your way

Common case: wget. Blocked case: a browser fingerprint. Hard case: a real browser. The first stage that works wins, and rewget remembers which one it was.

stage 1 · wget

Plain, fast, zero overhead

Runs wget (or wget2) with your exact flags. If the site does not block, you get the same output you would have got from wget directly. No daemon spin-up, no browser cost.

stage 2 · impersonate

Browser TLS and HTTP/2

rewgetd retries through rquest with a Chrome, Firefox, Safari, or Edge fingerprint. Most fingerprint-based blocks fold here without ever touching a real browser.

stage 3 · js preflight

Headless Chromium, on demand

When the page genuinely needs JavaScript, chromiumoxide drives Chromium, solves the challenge, exports cookies and headers, and stage 2 retries with the session.

Want the whole pipeline — CLI shim, rewgetd daemon, the per-domain cache, and signed profile updates? Read the architecture walkthrough →

What you get

Pragmatic defaults, explicit flags

Compatible

Drop-in wget replacement

Same flags, same output, same scripts. Add an alias and your existing automation keeps running. Nothing to learn, nothing to rewrite.

Stage 2

Browser-grade TLS fingerprints

When stage 1 returns 403, rewgetd retries the same URL with a real Chrome, Firefox, Safari, or Edge TLS and HTTP/2 fingerprint via rquest.

Stage 3

Headless Chromium when needed

For pages that genuinely need JavaScript, stage 3 spins up Chromium via chromiumoxide, solves the challenge, exports the session, and resumes the download.

Caching

Per-domain cache, 7-day TTL

Once rewget learns which stage works for a host, subsequent downloads skip straight there. The common case stays fast; the slow path runs once.

Security

Ed25519-verified profiles

Browser fingerprint profiles are signed and verified on update. New Chrome and Firefox releases roll out through --rewget-update-profiles, not silent network fetches.

Architecture

Daemon-backed, CLI-first

rewgetd owns the browser pool and TLS sessions. The CLI stays a thin shim — fast to start, cheap to call from scripts and Makefiles.

Usage

The flags you will actually use

basic — auto fallback
$ rewget https://example.com/file.tar.gz
CI — fail fast
$ rewget --rewget-no-fallback https://example.com/file.tar.gz
force browser preflight
$ rewget --rewget-js https://example.com/
pick a profile
$ rewget --rewget-profile=firefox136 https://example.com/

Where it earns its keep

Built for the jobs wget keeps failing

FAQ

Questions we get from people about to adopt this

+ Is rewget actually a drop-in replacement?

Yes. The CLI shim parses --rewget-* flags and forwards everything else unchanged to wget (or wget2 if you ask). If you alias wget=rewget, your existing scripts keep working. When a site does not block, you pay zero overhead — you get wget.

+ How does the three-stage fallback work?

Stage 1 runs plain wget. If it succeeds, that is the answer. If it fails on a fallback HTTP status (configurable via --rewget-fallback-codes), stage 2 retries through rquest using a browser TLS and HTTP/2 fingerprint. If stage 2 still fails, stage 3 launches headless Chromium to handle JavaScript challenges. The first stage that works wins.

+ Which browser profiles ship today?

Chrome 131 and 130, Firefox 136 and 133, Safari 18, and Edge 131. List them with --rewget-list-profiles. Update to the latest set with --rewget-update-profiles (Ed25519 verified).

+ Does it work on Windows?

The README lists Linux and macOS as the platform matrix today. We are not claiming Windows-native support until the release artifacts say so.

+ How do I install it?

Homebrew (brew install neul-labs/tap/rewget), npm (npm install -g rewget), PyPI (uv tool install rewget or pip install rewget), or cargo install rewget from source. There is also a one-line install script in the repo.

+ Can I disable the fallback for CI?

Use --rewget-no-fallback. The command fails fast on a block instead of escalating to stage 2 or 3. That is the right behaviour when you want CI to flag a regression instead of hiding it.

+ Does rewget bypass authenticated access control?

No. rewget handles fingerprint-based blocks and JavaScript challenges — the cases where a real browser would succeed and a plain HTTP client would not. If a site requires you to log in, rewget does not change that.

+ Is it really a single binary?

The CLI is. The daemon is a second binary that starts on demand and handles stage 2 and 3. Both ship from the same release; Homebrew, npm, PyPI, and the install script wire them together.

Explore the docs

Everything else worth reading

Every section of the site, one click deep. Start with how it works, or jump to the vocabulary and the questions people ask before adopting it.

Tired of wget: ERROR 403?

Install rewget, alias wget=rewget, and forget about it. When a site lets you in, it is plain wget. When it does not, rewget is already retrying.