# webrecorder/wombat: Client-Side URL Rewriting for Web Archive Replay

> Wombat is a standalone JavaScript library that overrides browser APIs so archived pages resolve their own URLs correctly during replay. It is built for web archiving engineers, not for general application development.

**webrecorder/wombat** — Wombat.js client-side rewriting library

- Repository: https://github.com/webrecorder/wombat
- Stars: 124 · Forks: 41
- Language: JavaScript
- License: AGPL-3.0
- Published: 2026-08-21 · Updated: 2026-08-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/webrecorder-wombat

## What problem webrecorder/wombat solves, and for whom

A page captured from the live web contains absolute and relative URLs that point at the original origin. Replay it from an archive and those URLs still point outward, so scripts fetch from the live site, links leave the archive, and workers load from the wrong place. Wombat exists to intercept those URLs inside the browser and redirect them through an archive prefix.

The README is explicit that the library is a standalone client-side URL rewriting system that performs its rewrites through targeted JavaScript overrides. It was originally shipped inside pywb and was later split into its own module, and the README states that pywb releases from 2.3 onward rely on this standalone module. That history explains the audience: people maintaining replay infrastructure, not people writing ordinary web applications. If you are not running an archive, a proxy recorder, or a replay front end, the library has nothing to offer you.

## Three bundles, three override surfaces

The build produces three files, and the README treats them as distinct products. wombat.js is the primary bundle and is used in both non-proxy recording and replay. Its entry point is src/wbWombat.js, which pulls in funcMap.js, customStorage.js, wombatLocation.js, listeners.js and autoFetchWorker.js. That list is a fair summary of what gets replaced: functions, storage, the location object, event listeners, and fetch behaviour.

wombatProxyMode.js is described as a stripped down version of wombat.js that applies a minimal set of overrides to support pywb's proxy recording mode. Its entry point is src/wbWombatProxyMode.js and it contains wombatLite.js plus autoFetchWorkerProxyMode.js. The third file, wombatWorkers.js, is called out as not really a bundle but a flat file providing the minimal overrides needed so that web and service workers behave correctly in both recording and replay.

The split matters when you choose what to inject. Replay needs the full override set; proxy recording needs the light one. Injecting the full bundle into a proxy recording context is more surface than the mode requires, and the README does not describe a supported way to mix the two.

## Installing webrecorder/wombat and injecting it into a page

The package is published as @webrecorder/wombat, and package.json lists main as index.js with version 3.10.8. Install it from npm:

```bash
npm install @webrecorder/wombat
```

The README frames the library around a build step that concatenates source files into bundles, so the practical path for a consumer is to produce the bundle and serve it from your replay application's static directory. The build scripts are declared in package.json:

```bash
npm run build-prod
```

That runs rollup -c rollup.config.prod.js. For iterating on the source, build-dev runs rollup with ALL=1 and build-dev-watch adds --watch, while build-dev-watch-proxy sets PROXY=1 to watch the proxy variant. Once the bundle exists, the replay server serves it and the replayed page loads it before the archived page's own scripts run. The README does not include a copy-paste HTML snippet for that injection, so where exactly the script tag goes is a decision your replay layer makes.

Tests run through ava:

```bash
npm test
```

The README states that this standalone module includes a testing suite that checks the correctness of the overrides against web standards, and package.json configures ava with concurrency 1 and serial true. That serial configuration is a useful signal: the suite is not designed to run in parallel.

## Where Wombat is the wrong tool

Wombat rewrites URLs at runtime by replacing browser APIs. That approach has a structural cost. Any API the bundle does not override behaves normally, and the README does not claim full coverage: it says the details of each file in a bundle are out of scope and points readers at the source comments instead. So the boundary of what is rewritten is defined by the source, not by a specification document.

A second constraint is that Wombat is client-side only. If your archive serves rewritten HTML and CSS at the server, Wombat does not replace that work; it handles the JavaScript-visible surface. Teams that want a single rewriting layer often find they need both.

The third case is anything outside replay. Wombat assumes it is running inside a page that has been captured and is being served back. Using it in a normal application to rewrite URLs would replace browser globals for no benefit, and the README offers no guidance for that use because it is not the intended one. The README also does not document rollback or a kill switch for a bundle that misbehaves in production, which is worth knowing before you ship it.

## Wombat against server-side rewriting in pywb

The obvious alternative is to do the rewriting before the response leaves the server, which is what pywb itself does for HTML, CSS and similar content. The difference in approach is timing and reach. Server-side rewriting sees the bytes of the response and can rewrite anything textual, including content inside inline scripts. Wombat sees the browser environment instead, so it can catch URLs constructed at runtime, passed to fetch, assigned to location, or read back from storage.

That reach is why the two are not substitutes. A replay system that only rewrites on the server will miss URLs a script builds from string concatenation after load. A system that only uses Wombat will miss content that is never touched by JavaScript. pywb releases from 2.3 onward rely on this standalone module, which is a reasonable indication that the project treats the two layers as complementary rather than competing. If you are choosing between them, the question is not which is better but which surface your archived pages actually exercise.

## Licence and the cost of keeping up

package.json declares the licence as AGPL-3.0-or-later, and the repository carries LICENSE.md and a NOTICE file. AGPL-3.0 is a strong copyleft licence with a network clause, which matters here because Wombat runs in the browser of a service users reach over a network. Whether your deployment triggers the network clause is a question for your own legal review; the repository does not offer guidance on it.

The maintenance picture is concrete. The repository is not archived, and the last push was on 2026-08-25, the same date as the v3.10.8 release. v3.10.7 followed on 2026-08-05 and v3.10.6 on 2026-07-29, so the release cadence over that window was roughly every few weeks. That cadence cuts both ways for an adopter: fixes arrive, and so does the need to re-run your replay tests against a new bundle. The README documents the build and test commands but says nothing about version compatibility between Wombat bundles and pywb releases, so pinning a version and testing an upgrade before rolling it out is the only defensible path.

## Conclusion

Adopt webrecorder/wombat only if you are building a replay or proxy recording system and need the browser API override layer that pywb >= 2.3 depends on. Do not adopt it as a general-purpose URL utility or as a front-end library: it assumes a replay context and an external rewriter. Before committing, verify that your rewriter can supply the prefix Wombat expects, that your target browsers match the override surface documented in src/wbWombat.js, and that AGPL-3.0-or-later fits your distribution model.

## FAQ

### How do you install webrecorder/wombat?

It is published on npm as @webrecorder/wombat, so npm install @webrecorder/wombat fetches it. The README describes the library as producing bundles through a build step, and package.json declares a build-prod script that runs rollup with rollup.config.prod.js.

### What is webrecorder/wombat?

It is a standalone client-side URL rewriting system that performs rewrites through targeted JavaScript overrides. It was originally distributed as part of pywb and was later split into its own module, and pywb releases from 2.3 onward rely on it.

### How do you use webrecorder/wombat?

You build one of the three bundles (wombat.js, wombatProxyMode.js or wombatWorkers.js) and load it in the replayed page so its overrides are in place before the archived page's scripts run. Which bundle you pick depends on whether you are doing replay or pywb's proxy recording mode.

### Which bundle should I use for proxy recording rather than replay?

The README describes wombatProxyMode.js as a stripped down version of wombat.js that applies a minimal set of overrides to support pywb's proxy recording mode. The full wombat.js is the primary bundle used in both non-proxy recording and replay.

### What licence does webrecorder/wombat use?

package.json declares AGPL-3.0-or-later, and the repository includes LICENSE.md and a NOTICE file. The repository does not discuss how the network clause applies to a given deployment.

## Sources

- [Official README](https://github.com/webrecorder/wombat#readme)
- [Project repository](https://github.com/webrecorder/wombat)
- [Release notes](https://github.com/webrecorder/wombat/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/webrecorder-wombat
