Self-hosted service
Ray-D-Song/web-archive avatar
Ray-D-Song/web-archive

web-archive: a Cloudflare-native archive service that saves pages as single HTML files

Selfhost web archiving and sharing service.

933 stars291 forksTypeScriptGPL-3.0

At a glance

What is it?
Ray-D-Song's web-archive splits archiving into three pieces: a browser extension that captures a page as one HTML file, a Cloudflare Worker backend backed by D1 and R2, and a web client for reading and sharing. It is a good fit if you already live inside Cloudflare's free tier and want a personal archive you control.
Who is it for?
Adopt web-archive if you want a personal or small-team archive that lives entirely inside a Cloudflare account you control, and you accept that the capture format is a single HTML file produced by the extension rather than a WARC. Do not adopt it if you need standards-compliant preservation output, long-term replay fidelity guarantees, or a backend that runs on ordinary Linux hosts without Wrangler.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 142 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What web-archive actually captures, and who needs that

The project's stated purpose is narrow: save a webpage as a single HTML file, upload it to a server you run, and read or share it later. That is a different goal from web preservation in the archival sense. The README describes the browser plugin as the component that saves the page and uploads it, and the server as the component that receives the file and stores it in a database and a storage bucket. Nothing in the supplied material mentions WARC, WACZ, or any format used by institutional archives. The unit of preservation here is one self-contained HTML file per page.

That choice defines the audience. If you read a lot of long articles, documentation pages, or forum threads and want them retrievable after the original goes offline or changes, a single-file capture is convenient: it is portable, it opens in any browser, and it does not require a replay stack. If your requirement is legal or scholarly provenance, byte-level fidelity, or replay of complex interactive applications, this is the wrong tool before you even install it.

The feature list is short and practical: archiving, search, sharing, folder classification, mobile adaptation, AI generated tag classification, and a reading mode. The presence of reading mode suggests the author expects saved pages to be read again inside the client, not merely stored.

Three components, one Cloudflare account

The architecture described in the README is a straight line. The extension captures the page and uploads the HTML file. The server accepts the upload and writes it into two places: the D1 database and the R2 storage bucket. The web client queries the stored file and renders it. The README states the server is based on the full set of Cloudflare Worker services, which is why D1 and R2 appear as the persistence layer rather than a conventional database and filesystem.

The split between D1 and R2 is the part worth thinking about. D1 is Cloudflare's SQL database and R2 is its object storage. A design that writes the same artifact to both could mean metadata (title, URL, folder, tags) lives in D1 while the HTML body lives in R2, or it could mean the file is stored in both for redundancy. The README does not spell out which, and I cannot confirm the schema from the material provided. If you are evaluating this for a large archive, that ambiguity matters: it determines whether your storage cost scales with raw page size or with something smaller.

The Worker model also means there is no long-running process to babysit. Requests come in, the Worker handles them, D1 and R2 answer. The trade-off is that everything you can do is bounded by what Cloudflare's runtime and bindings allow. There is no cron job scanning your archive for link rot, no background re-crawl, and no local filesystem to inspect when something goes wrong.

Deploying it: Docker first, Cloudflare for real use

The README gives one literal command, and it is the Docker path:

docker run -d -p 8787:8787 -v web-archive-data:/app/service/.wrangler/state ghcr.io/ray-d-song/web-archive:latest

Read the volume mount carefully. It points at /app/service/.wrangler/state, which is Wrangler's local state directory. That tells you the Docker image runs the Worker through Wrangler's local emulation rather than against real Cloudflare services. For a trial run or a single-user instance on a home machine, that is fine and it explains why the container is self-contained. It also means the Docker path is not the same thing as a production Cloudflare deployment.

The README calls Cloudflare the recommended deployment and points to web-archive-docs.pages.dev/en/deploy.html for the procedure. It does not reproduce the binding configuration or the wrangler.toml contents in the README itself, so I cannot state the exact D1 database name, R2 bucket name, or secret variable names from the material I have. Anyone deploying should treat that deploy document as the source of truth rather than guessing at config keys.

After deployment, the README says to enter the service address and key into the browser plugin. That key is the access control boundary for the whole service. There is no mention of user accounts, roles, or per-user isolation, which is consistent with a personal archiving tool rather than a multi-tenant service. The plugin is distributed through the Chrome Web Store and Firefox Add-ons, so you do not build the extension yourself to get started.

The limitations the README does not advertise

The most consequential constraint is the capture format. A single HTML file is a snapshot produced by the extension at the moment you press save. Anything the page loads later, any API-backed content, any state that depends on your session, will not be in that file. The README does not describe how the extension handles iframes, cross-origin resources, or pages that render entirely client-side. If you archive a lot of JavaScript-heavy sites, expect gaps, and verify against your own targets before trusting the archive.

Second, the Docker command binds port 8787 and mounts a named volume. There is no mention of TLS termination, reverse proxy configuration, or authentication beyond the service key. Exposing that port directly to the internet without putting something in front of it would leave the archive reachable by anyone who can guess or obtain the key.

Third, the release cadence is uneven. v0.1.2 and v0.1.3 landed eight days apart in December 2024, then v0.2.0 arrived in April 2026, roughly sixteen months later. A gap that long between minor versions usually means either the project was stable and untouched, or it was dormant. The material does not tell us which, and I will not guess. If you are planning to depend on this for years, that history is the thing to weigh, not the feature list.

Fourth, the AI generated tag classification feature implies an external model call or a Workers AI binding. The README does not say which, what it costs, or whether it can be disabled. On a free-tier Cloudflare account, that is a question worth answering before you enable it.

How it differs from ArchiveBox and wallabag

ArchiveBox is the closest comparison in intent: a self-hosted archiving tool you run yourself. The difference is in the output and the runtime. ArchiveBox is typically deployed as a Python application on a server or in Docker and produces multiple formats per capture, commonly including WARC alongside rendered HTML and screenshots. web-archive produces one HTML file and stores it in D1 and R2 through a Cloudflare Worker. If you want a preservation-grade artifact you can hand to an institution, ArchiveBox's output is closer to what those workflows expect. If you want a personal archive with no server to patch and no disk to fill, web-archive's serverless shape is the point.

wallabag is a read-later service, not an archiving service. It extracts article text for comfortable reading and stores that, which is excellent for articles and poor for anything where the original layout carries meaning. web-archive's reading mode overlaps with wallabag's core function, but the stored artifact is the full page rather than an extraction. That makes web-archive better for pages you want to see as they were, and worse for the pure reading queue use case where wallabag's extraction is the feature.

The honest framing: web-archive trades preservation rigor for operational simplicity. You get a Worker, a database, a bucket, and a browser extension. You give up WARC output and the tooling ecosystem built around it.

Licence, maintenance and upgrade cost

web-archive is GPL-3.0. If you fork it and distribute modified versions, the GPL's source disclosure and same-licence conditions apply to what you distribute. Running it privately for yourself does not trigger distribution obligations in the ordinary case, but I am not a lawyer and this is not legal advice. If you plan to offer it as a service to others, or to ship a modified extension, read the licence text and get proper advice.

On maintenance: the moving parts are the Worker code, the D1 schema, the R2 bucket contents, and the browser extension. The extension is distributed through the Chrome Web Store and Firefox Add-ons, so when the server API changes, the published extension has to keep working or users must update. v0.2.0 followed v0.1.3 by roughly sixteen months, which means an upgrade may span a large set of changes. The README does not include a migration guide or a changelog summary in the material provided, so check the release notes for v0.2.0 before upgrading an existing instance.

The Docker volume at /app/service/.wrangler/state holds your local data. Back it up before pulling a new image, because a schema change in the Worker could make that state unreadable to the new version.

If you deploy on Cloudflare, your ongoing cost is whatever D1 and R2 charge beyond the free tier, plus any cost attached to the AI tagging feature. The repository topics include the word free, and the README calls it a free service, but that describes the software licence and the free-tier fit, not a guarantee that storage will stay free as your archive grows.

Who should run this, and what to check first

Run web-archive if you are a single user or a small group, you already have or are willing to create a Cloudflare account, and you want saved pages you can open in a browser without a replay stack. The Docker command is a reasonable way to try it before committing to Cloudflare, and the extension installs from the standard stores.

Do not run it if you need WARC or another preservation-standard format, if you need multi-user accounts with isolation, or if your infrastructure policy forbids putting data in Cloudflare's storage services. Do not run it expecting the archive to survive the disappearance of the extension, since the capture step depends on it.

Before you commit, three checks. First, open web-archive-docs.pages.dev/en/deploy.html and confirm the D1 and R2 binding names and the secret the extension authenticates with, because the README does not list them. Second, read the v0.2.0 release notes for breaking changes if you are upgrading from v0.1.x, given the sixteen-month gap. Third, save three pages you actually care about, including one heavy JavaScript site, and open them with the network disconnected. If those three replay correctly, the tool does what you need. If they do not, the format is the reason, and no amount of configuration will fix it.

Editorial conclusion

Adopt web-archive if you want a personal or small-team archive that lives entirely inside a Cloudflare account you control, and you accept that the capture format is a single HTML file produced by the extension rather than a WARC. Do not adopt it if you need standards-compliant preservation output, long-term replay fidelity guarantees, or a backend that runs on ordinary Linux hosts without Wrangler. Before deploying, read the deploy document at web-archive-docs.pages.dev/en/deploy.html to confirm the current D1 and R2 binding names, check whether v0.2.0 changed the API surface the extension talks to, and verify the GPL-3.0 obligations if you plan to modify and redistribute the Worker code.

Official sources

  1. License: GPL-3.0
  2. Project website
  3. Ray-D-Song/web-archive on GitHub
  4. README
  5. Releases
Community notes

Community notes