Shoot before the blink
Haylxon(hxn) — is a fast, minimal screenshot tool for webpages using Chrome's headless mode. Supports local and remote browsers, tab pooling, and parallel execution.
- Local or remote — launch a local browser or connect to a remote Chromium instance via CDP
- Tab pooling — reuse browser tabs across URLs instead of spawning new ones every time
- Parallel — configurable concurrency with
--tabs - Flexible input — single URL, file, or stdin
- Output formats — PNG, JPEG, WebP, fullpage, NDJSON metadata
- Portable — Linux, macOS, Windows, Termux
Binary
Download from releases, or:
wget -qO- "$(curl -qfsSL "https://api.github.com/repos/pwnwriter/haylxon/releases/latest" \
| jq -r '.assets[].browser_download_url' \
| grep -Ei "$(uname -m).*$(uname -s).*musl" \
| grep -v "\.sha")" | tar -xzf - --strip-components=1 && ./hxn -hCargo
cargo install hxn
# or with binstall
cargo binstall hxnSource
git clone --depth=1 https://github.com/pwnwriter/haylxon
cd haylxon && cargo build --releaseNix
nix run github:pwnwriter/haylxon
# or
nix profile install nixpkgs#haylxonArch Linux
paru -S haylxon-gitTermux
pkg install tur-repo -y && pkg install chromium -y
ln -s "$PREFIX/bin/chromium-browser" "$PREFIX/bin/chromium"Examples use
brave— any Chromium-based browser works. Swap-b $(which brave)with your browser path.
# Single URL
hxn -b $(which brave) -u https://example.com
# From a file
hxn -b $(which brave) -f urls.txt
# From stdin
cat urls.txt | hxn -b $(which brave) --stdinRemote browser
Connect to an already-running Chromium instance instead of launching one locally.
# On the remote machine
chromium --headless --remote-debugging-port=9223 --no-sandbox
# Chrome often ignores --remote-debugging-address=0.0.0.0, so expose it with socat
socat TCP-LISTEN:9223,fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:9223 &
# Auto-discover the WebSocket endpoint (recommended)
hxn --remote-host 192.168.1.42:9223 -f urls.txt
# Or pass the WebSocket URL directly
hxn --remote-url ws://192.168.1.42:9223/devtools/browser/<uuid> -u https://example.comTab pooling
Tabs are reused by default. Pages are reset between URLs instead of being created and destroyed each time.
# Custom pool size (default: 8)
hxn -b $(which brave) -f urls.txt --pool-size 16
# Disable tab reuse
hxn -b $(which brave) -f urls.txt --reuse-tabs falseScreenshots
# Fullpage
hxn -b $(which brave) -u https://example.com --fullpage
# JPEG format
hxn -b $(which brave) -u https://example.com --screenshot-type jpeg
# Custom viewport
hxn -b $(which brave) -u https://example.com -x 1920 -y 1080Advanced
# Parallel tabs
hxn -b $(which brave) -f urls.txt --tabs 8
# With ports
hxn -b $(which brave) -f urls.txt --ports 8080,8081
# Proxy
hxn -b $(which brave) -u https://example.com --proxy socks5://127.0.0.1:9050
# Random user agent
hxn -b $(which brave) -f urls.txt --user-agent "random"
# Run JavaScript before screenshot
hxn -b $(which brave) -u https://example.com --javascript "document.querySelector('.banner')?.remove()"
# NDJSON output
hxn -b $(which brave) -f urls.txt --json
# Silent mode
hxn -b $(which brave) -f urls.txt --silent
# Timeout and delay
hxn -b $(which brave) -f urls.txt --timeout 200 --delay 5
# Accept invalid certs
hxn -b $(which brave) -f urls.txt --accept-invalid-certsComparison with gowitness on GitHub Actions (ubuntu-latest), measured with hyperfine. Full run.
| Benchmark | hxn | gowitness | Result |
|---|---|---|---|
| Single URL | 360ms | 3.99s | hxn 11x faster |
| 5 URLs, 4 tabs | 1.81s | 26.29s | hxn 14x faster |
| 5 URLs, 8 tabs | 1.70s | 14.67s | hxn 8x faster |
Contributions welcome via issues or pull requests.
Copyright © 2023 - present pwnwriter
