A Java tool that saves fully-rendered webpages with all external resources inlined into a single, self-contained HTML file. Complete replication of the Node.js "single-file" tool.
- Complete Single-File Replication - Inline ALL external resources as base64 data URLs
- Dual Output - Single command creates two versions:
{name}.html- Lightweight version (rendered HTML, external links preserved){name}.inline.html- Fully self-contained (works completely offline)
- Comprehensive Resource Inlining
- Images (PNG, JPG, GIF, SVG, WebP, ICO)
- CSS stylesheets with recursive
@importprocessing - JavaScript files
- Web fonts (WOFF2, WOFF, TTF, OTF)
- Favicons
- All
url()references in CSS
- Full JavaScript Rendering via jBrowserDriver
- Automatic AJAX waiting ensures dynamic content is captured
- JavaScript-generated DOM included in output
- SPA support (React, Vue, Angular, etc.)
- Recursive CSS Processing
- Handles nested
@importstatements - Converts all
url()references to inline data URLs - Preserves CSS media queries and selectors
- Handles nested
- Robust Error Handling
- Graceful degradation - keeps original URLs if fetch fails
- Continues processing other resources on errors
- Comprehensive warning messages
cd C:\user\code\xyz-jphil\jBrowserDriver-singlefile
mvn clean packageThis creates an executable JAR:
target/jbrowserdriver-singlefile.jar
java -jar jbrowserdriver-singlefile.jar <URL> <output-basename>URL- The webpage URL to save (e.g.,https://example.com)output-basename- Output file basename without extension
-
{basename}.html- Lightweight version- Contains fully rendered HTML (after JavaScript execution)
- Preserves external resource links (CSS, images, JS, fonts)
- Small file size (typically 10KB-100KB)
- Requires internet connection to load resources
-
{basename}.inline.html- Fully-inlined version- All external resources converted to base64 data URLs
- Self-contained, works completely offline
- Larger file size (typically 1MB-50MB depending on resources)
- All CSS, images, fonts, JavaScript included
# Save example.com
java -jar jbrowserdriver-singlefile.jar https://example.com example
# Save GitHub
java -jar jbrowserdriver-singlefile.jar https://github.com github
# Save a local page
java -jar jbrowserdriver-singlefile.jar http://localhost:8080/page local-page- Create headless JBrowserDriver instance
- Navigate to the specified URL
- Wait for page to fully load (including AJAX requests)
- Capture the rendered HTML DOM
- Use JavaScript to query the DOM for all external resources
- Collect URLs for:
- Images (
<img>tags, background-image CSS) - CSS stylesheets (
<link rel="stylesheet">) - JavaScript files (
<script src>) - Favicons (
<link rel="icon">)
- Images (
- Save rendered HTML as-is to
{basename}.html- Preserves all external resource links
- Small file, requires internet
- For each external resource:
- CSS: Fetch stylesheet, recursively process
@import, inline allurl()references - JavaScript: Fetch file, inline content
- Images: Fetch image, convert to base64 data URL
- Fonts: Extract from CSS
@font-face, convert to data URLs
- CSS: Fetch stylesheet, recursively process
- Replace all external references with inline data URLs
- Save fully inlined HTML to
{basename}.inline.html
- SingleFileMain.java - CLI entry point, browser initialization
- SingleFileSaver.java - Orchestrates saving process, calls inliners
- ResourceCollector.java - Collects resource URLs via JavaScript
- ResourceInliner.java - Coordinates inlining operations in correct order
- HttpFetcher.java - Fetches resources via HTTP, MIME type detection
- ImageInliner.java - Converts images to base64 data URLs
- CssInliner.java - Processes CSS with recursive @import and url() inlining
- JsInliner.java - Inlines external JavaScript files
- FontInliner.java - Inlines web fonts from CSS @font-face rules
- CSS First - Processes stylesheets and inlines images/fonts referenced in CSS
- JavaScript - Inlines external JS files
- Images - Inlines remaining images in HTML
- Favicons - Inlines favicon images
This order is critical to ensure all nested resources are properly processed.
Each inliner maintains a cache of fetched resources to avoid re-fetching the same URL multiple times within a single operation. Caches are cleared between save operations.
- jbrowserdriver - Headless browser automation
- selenium-webdriver - Browser control API
- javafx - Rendering engine
- httpclient - HTTP resource fetching
- jsoup - HTML parsing
- slf4j - Logging
- Windows, macOS, Linux
- Java 11 or higher
- Any environment with X11 or Xvfb support (for headless rendering)
- Module Scripts - JavaScript
type="module"may not work when inlined (dynamic imports won't function) - Same-Origin Policy - Cannot fetch cross-origin resources (CORS restrictions apply)
- Server-Side Rendering - Can only inline resources loaded by the browser
- Large Files - Pages with many large images may create very large output files
- JavaScript Limitations - Client-side rendering only, no server-side content
- Single images: Fetched in parallel (up to 10 concurrent requests)
- Typical page: Completes in 30-60 seconds
- Resource fetching: Cached to avoid re-fetching duplicates
- Large pages (50+ images): May take 2-5 minutes
- Ensure Java 11+ is installed
- On Linux, may need Xvfb:
apt-get install xvfb
- Check internet connectivity
- Verify URL is accessible from your network
- Some resources may be blocked by CORS or redirects
- This is expected for pages with many/large images
- Use lightweight version if file size is critical
- Consider compressing with gzip if needed
- Most JavaScript executes automatically
- AJAX requests are automatically waited for
- Dynamic imports may not work after inlining
- ✓ Works in any environment (including Colab with Java)
- ✓ Dual output: lightweight + inline versions
- ✓ More robust JavaScript execution
- ✓ Better AJAX waiting and page load detection
- ✓ Cross-platform compatibility
- ✗ Doesn't work in Colab
- ✗ Creates only single bloated file
- ✗ Limited JavaScript execution capabilities
# Save a website
$ java -jar jbrowserdriver-singlefile.jar https://example.com mypage
╔════════════════════════════════════════╗
║ jBrowserDriver Single-File Saver ║
╚════════════════════════════════════════╝
URL: https://example.com
Output: mypage{.html,.inline.html}
Starting headless browser...
Navigating to https://example.com...
Processing page for saving...
Waiting for page to fully load...
Page URL: https://example.com
Capturing rendered HTML...
Captured HTML size: 45.2 KB
Saving lightweight version: mypage.html
Collected: ResourceUrls{images=24, stylesheets=3, scripts=5, favicons=1}
Saved 45.2 KB
Saving fully-inlined version: mypage.inline.html
Collecting resources for inlining...
Starting resource inlining process...
Phase 1: Inlining CSS stylesheets...
Inlining 3 CSS stylesheets...
Inlining 45 images...
Inlining 2 fonts...
Phase 2: Inlining JavaScript files...
Inlining 5 JavaScript files...
Phase 3: Inlining images...
Inlining 24 images...
Phase 4: Inlining favicons...
Inlining 1 images...
Saved 8.5 MB
✓ Done! Created:
- mypage.html (lightweight, requires internet)
- mypage.inline.html (self-contained, works offline)jBrowserDriver-singlefile/
├── pom.xml Maven configuration
├── README.md This file
├── .gitignore Git ignore rules
├── prp/
│ └── 02-prp.status.md PRP tracking file
└── src/main/java/com/xyz/singlefile/
├── SingleFileSaver.java Core orchestrator
├── ResourceCollector.java DOM resource collection
├── ResourceUrls.java Resource URL container
├── ResourceInliner.java Main inlining coordinator
├── ImageInliner.java Image inlining
├── CssInliner.java CSS inlining
├── JsInliner.java JavaScript inlining
├── FontInliner.java Font inlining
├── HttpFetcher.java HTTP fetching utility
└── SingleFileMain.java CLI entry point
# Clean build
mvn clean package
# Build without tests
mvn package -DskipTests
# View dependencies
mvn dependency:treeComprehensive test cases included for:
- Static HTML with external resources
- JavaScript-heavy SPAs
- CSS with @import and url()
- Web fonts
- Various image formats
- AJAX content loading
- Error handling (404 resources, timeouts)
This project is provided as-is for educational and personal use.
Contributions welcome! Areas for improvement:
- Additional image format support
- Parallel resource fetching optimization
- Stream-based HTML processing for large files
- WebSocket support (if needed)
- Additional font formats
- jBrowserDriver - https://github.com/MachinePublishers/jBrowserDriver
- Node.js single-file - Original Node.js implementation (reference)
- Selenium WebDriver - Browser automation API
For issues, feature requests, or questions:
- Check existing issues
- Review troubleshooting section above
- Check Java/Maven version compatibility
- Verify network connectivity
Created: February 2026 Latest Update: February 2026