About
We did not want to argue. We wanted the download.
rewget started as a half-hour rant on a Slack channel. The rant ended with "if wget had the right TLS fingerprint, the download would have just worked." Two weeks later we had a working prototype. This is the long version of that rant.
The problem with bare wget in 2026
wget is one of the most widely deployed CLI tools in the world. It is in your Dockerfiles, your CI runners, your install scripts, your VM bootstrap. It is the right shape for what it does — resumable, recursive, fire-and-forget downloads with a flag for every option you might ever need.
It also gets blocked. Not because the people running the sites are hostile to scripts, but because the WAFs they run in front of them flag any HTTP client that does not look like a browser. The TLS fingerprint is wrong. The HTTP/2 frame ordering is wrong. The headers are too clean. The result is a 403, or a CAPTCHA page, or a 429 with a fifteen-minute cooldown.
You can work around this. Fork off curl with --tlsv1.3 --http2. Hand-pick a User-Agent. Write a Python script that drives Playwright. By the end of the day you have a Frankenstein pipeline that is harder to read than the thing it replaced, and the next week a new site blocks it for a slightly different reason.
What rewget actually is
rewget is a thin CLI shim that runs wget for you, watches the result, and escalates if wget hits a block.
- Stage 1 is plain wget (or wget2). No daemon spin-up, no overhead. If the download succeeds, you get the exact same output, byte for byte, that wget would have produced.
- Stage 2 is rewgetd, a sidecar daemon, retrying the same URL through
rquestwith a real browser TLS and HTTP/2 fingerprint. Most fingerprint-based blocks fold here. - Stage 3 is a headless Chromium via
chromiumoxide, driven by rewgetd to solve JavaScript challenges. When the page genuinely needs a browser, this is the only honest answer.
The first stage that works wins. The domain-level cache records which stage worked and the next download from that host skips straight to it for seven days.
What rewget is not
It is not a curl replacement. The CLI shape is different on purpose; we wanted the wget muscle memory to keep working, not to relitigate a twenty-year-old argument. Use curl when curl is right.
It is not a way to bypass authenticated access control. If the site needs you to log in, rewget will not change that.
It is not Windows-native today. The platform matrix in the README lists Linux and macOS. When that changes we will say so on the release page, not on a marketing site.
What we built it with
Rust, with Tokio async. rquest for stage 2 fingerprinting. chromiumoxide for headless Chromium. nng for IPC between the CLI and the daemon. mimalloc for allocation. Three crates — rewget, rewgetd, rewget-core — sharing detection, caching, and profile logic.
The release artifacts ship from cargo build --release with LTO, stripped binaries, and codegen-units pinned to 1. Profiles for Chrome 131 and 130, Firefox 136 and 133, Safari 18, and Edge 131 are signed with Ed25519 and verified on update.
Who runs neul-labs
neul-labs builds small, sharp tools that close the gap between what a browser does and what your scripts can do. rewget is the most concrete one to date. There are siblings — recurl for the curl-shaped version of the same problem; more on the way — but rewget is the one you reach for when the download has to work.
How to engage
Install rewget. Alias wget=rewget. Open issues on GitHub. If the three-stage strategy fails on a site you care about, tell us — that is the most useful bug report we can get, because it means a stage-3 profile or a fallback-code default needs updating.
Read the docs at rewget.docs.neullabs.com. Pin a version. Update on your schedule, not ours.