Simple Archiver Bot -- a suckless web archiver written in C.
sbot creates self-contained archives of web pages and entire websites. Every resource -- CSS, images, fonts, scripts -- is fetched and inlined directly into the HTML as base64 data URIs. The result is a single file (or directory of files) that renders perfectly offline, with no external dependencies, forever.
Web pages disappear. Link rot is real. The average web page has a half-life of about two years. Bookmarks break, articles vanish, references evaporate.
sbot solves this by creating archives that are:
sbot https://example.com/article
Archives a single page in GWTAR format (Gwern Web Tar Archive). This
is the default mode and the most common use case. The output is one
.gwtar.html file containing:
<style> blocksdata: URIsGWTAR format is ideal for:
sbot -r https://example.com
Recursively crawls an entire website and archives every page. The output is a directory tree that mirrors the site structure, with each page saved as a self-contained HTML file. Internal links are rewritten to relative paths so navigation works offline.
Features:
-R.-d to limit scope.This mode is ideal for:
usage: sbot [-vrR] [-d depth] [-o dir] [-a author] url
-v verbose output
-r recursive (crawl entire site)
-R ignore robots.txt
-d depth max crawl depth (default: 5)
-o dir output directory
-a author site author name
# Archive a single article
sbot https://example.com/blog/post
# Archive with author metadata
sbot -a "John Doe" https://example.com/article
# Crawl a blog, max depth 3
sbot -r -d 3 https://blog.example.com
# Verbose crawl to custom directory
sbot -v -r -o ./my-archive https://docs.example.com
# Crawl ignoring robots.txt restrictions
sbot -r -R https://example.com
Every archived page includes a GWTAR (Gwern Web Tar Archive) metadata header as an HTML comment at the top of the file:
<!--
================================================================
GWTAR ARCHIVE
================================================================
Title: Example Article
Source URL: https://example.com/article
Domain: example.com
Author: John Doe
Archived by: Kris Yotam
Archived on: krisyotam.com
Archive date: 2026-02-14
Generator: sbot/0.3.0
Format: GWTAR (Gwern Web Tar Archive)
================================================================
-->
This header provides full provenance tracking: what was archived, where it came from, who archived it, and when.
sbot inlines all resources to create truly self-contained archives:
| Resource Type | Inlining Method |
|---|---|
| CSS stylesheets | Fetched and inserted as <style> blocks |
| Images | Base64-encoded as data:image/* URIs |
| Fonts | Base64-encoded as data:font/* URIs |
| Other media | Base64-encoded with appropriate MIME type |
Resources that fail to fetch are silently skipped -- the archive degrades gracefully rather than failing entirely.
Requires libcurl development headers.
# Arch Linux
sudo pacman -S curl
# Debian/Ubuntu
sudo apt install libcurl4-openssl-dev
# Build
make
# Install to /usr/local/bin
sudo make install
# Clean
make clean
All configuration is compile-time via config.h:
| Setting | Default | Description |
|---|---|---|
USER_AGENT |
sbot/0.3 |
HTTP User-Agent string |
CONNECT_TIMEOUT |
30s | Connection timeout |
REQUEST_TIMEOUT |
60s | Total request timeout |
MAX_REDIRECTS |
10 | Maximum HTTP redirects to follow |
MAX_DEPTH |
5 | Default recursive crawl depth |
RATE_LIMIT_MS |
1000ms | Delay between requests |
MAX_FILE_SIZE |
50 MB | Maximum size per resource |
OUTPUT_EXT |
.gwtar.html |
File extension for archives |
Edit config.h and rebuild to change any setting. This is the suckless
way -- no runtime configuration files, no environment variables, no
hidden defaults.
archiver.c Main entry, page archiving, CSS inlining, link rewriting
crawl.c URL queue (BFS), visited set, URL normalization
fetch.c HTTP fetching via libcurl
parse.c HTML parsing, resource extraction, image inlining
robots.c robots.txt fetching, parsing, rule matching
util.c Memory wrappers, string ops, base64, MIME types
config.h Compile-time constants
Single external dependency: libcurl. No XML parsers, no HTML5 parsers,
no JavaScript engines. The HTML parsing is deliberately simple --
regex-based extraction of src, href, and url() references. This
handles the vast majority of real-world pages and keeps the codebase
small and auditable.
sbot follows the suckless philosophy:
config.h (edit and recompile)MIT/X Consortium License. See LICENSE for details.