I Stored a Website in a Favicon — AI article on gikiewicz.com

A single favicon file can hold roughly 4 KB of data. That is enough to store a complete, functional website — HTML, CSS, and JavaScript — inside what browsers treat as a tiny decorative icon. The technique sounds like a parlor trick. It is actually a working proof-of-concept that exposes how browsers handle embedded data.

TL;DR: A developer demonstrated that an entire static website can be encoded into a favicon file using base64 data URIs and the browser’s native favicon rendering pipeline. The favicon format supports multi-resolution ICO structures, and when the browser requests /favicon.ico, the server can deliver a payload that functions as both an icon and a self-contained document. The project shows that even the smallest web assets can carry surprising amounts of executable content.

How Does a Favicon Store an Entire Website?

The method relies on the ICO file format’s built-in tolerance for extra data. An ICO file contains an image directory header followed by one or more embedded images — typically PNG or BMP. The format specification does not strictly forbid additional data appended after the valid image payload. Browsers parse the header, extract the image, and ignore anything beyond it. That ignored space is where the website lives.

The developer behind this experiment, Tim Wehrle, had previously stored two bytes inside a mouse’s DPI register. That earlier project was, by his own description, not useful and not practical. But it triggered a line of thinking about what other overlooked storage locations exist in everyday computing hardware and software. A favicon is one of the most universally requested files on the web. Every browser, every tab, every bookmark triggers a request for one.

The actual encoding process works through base64 data URIs embedded within the HTML document itself. The website’s HTML, CSS, and JavaScript are minified and compressed into a single string. That string is then placed inside the ICO file structure alongside a valid minimal PNG image. When a browser downloads the favicon, the embedded JavaScript can execute through specific delivery mechanisms. The result is a file that looks like a normal icon but contains a full interactive page.

What Is the ICO File Format and Why Does It Matter Here?

The ICO format dates back to Windows 1.0 in 1985. It was designed to store icons for the operating system’s graphical interface. Unlike simpler image formats, ICO is essentially a container — a directory of images at different sizes and color depths. A single ICO file might contain a 16×16 pixel image, a 32×32 image, and a 48×48 image, each using different bit depths. This multi-image structure means the format already expects to hold more data than a single picture.

The file begins with a 6-byte header: two bytes identify it as an ICO (always 00 00 01 00), and two bytes specify the number of images. Each image entry in the directory occupies 16 bytes, describing width, height, color palette, and the offset where the actual image data begins. The image data itself can be PNG, BMP, or another format embedded raw. This is where things get interesting for data hiding.

Because the ICO format uses explicit offsets to locate image data, any bytes sitting between the directory entries and the image data — or after the final image — are simply never read by the parser. A browser requesting a favicon cares about rendering a small icon. It reads the directory, finds the best-sized image, extracts it, and discards everything else. That architectural indifference creates a hiding spot.

How Much Data Can Realistically Fit Inside a Favicon?

The practical limit depends on how browsers and servers handle large favicon payloads. Standard favicons range from a few hundred bytes to about 4 KB for a multi-resolution ICO. However, there is no hard-enforced maximum on favicon file size across most browsers. Chrome, Firefox, and Safari will all download and process favicons exceeding 100 KB without complaint. The constraint is not technical — it is behavioral.

Server-side configurations often impose limits. Many CDNs and web servers cap static asset sizes or apply aggressive caching rules. A favicon that is unusually large may trigger security warnings or get flagged by WAF (Web Application Firewall) rules. In testing, the developer found that payloads in the range of 10–50 KB were reliably delivered across major browsers without errors. That is enough space for a minified HTML page with inline CSS and a substantial JavaScript application.

Compression dramatically extends what fits. Gzip-compressed HTML can shrink by 70–80%, meaning a 40 KB raw payload might compress to under 10 KB. When the browser decompresses the response, the full application becomes available. The tradeoff is latency — a larger favicon takes longer to download, and the browser’s favicon request is typically low-priority on the page load waterfall.

What Are the Practical Use Cases for Favicon-Based Storage?

The most immediate application is content persistence in environments where traditional hosting is blocked or unavailable. A favicon can be cached aggressively by browsers — sometimes for months. That cached favicon, containing a full application, remains accessible even when the originating server goes offline. This makes the technique relevant for censorship circumvention, where users need access to tools or information that authorities attempt to suppress.

Another use case is digital watermarking and steganography. A company could embed tracking identifiers, copyright information, or licensing data inside its favicon. The embedded data would travel with the icon wherever it is copied or cached. Unlike visible watermarks, this data is invisible to end users and survives most copying operations.

Security researchers have also noted the potential for malicious payloads. A favicon containing JavaScript could be used as a delivery mechanism in sophisticated attacks. Because favicons are automatically requested by browsers and rarely inspected by security tools, they represent a blind spot in many web filtering pipelines. The technique is not inherently malicious, but it demonstrates why security teams need to inspect all downloaded assets — not just HTML and JavaScript files.

How Do Browsers Actually Process Favicon Requests?

When a browser navigates to a URL, it performs dozens of requests in parallel. One of the earliest is the favicon request, typically sent to /favicon.ico at the root domain. The browser looks for a <link rel="icon"> tag in the HTML <head> section first. If none is found, it falls back to the default /favicon.ico path. This request happens for virtually every page load, making it one of the most predictable HTTP requests on the web.

The response is processed by the browser’s image decoding pipeline. The browser determines the file format — ICO, PNG, SVG, or GIF — and renders the appropriate resolution for the current display context. Tab bars typically use 16×16 pixel renderings, while bookmark pages and home screen icons may request larger sizes. Once decoded, the favicon is stored in the browser’s favicon database, a SQLite file that persists across sessions.

This persistence is what makes favicon-based storage powerful. The SQLite favicon database in Chrome, for instance, can retain entries for months. A cached favicon with an embedded payload remains retrievable long after the user has navigated away from the original site. The browser never voluntarily clears favicons unless the user explicitly clears browsing data. Even then, favicons are sometimes retained due to bugs or implementation quirks in the cache-clearing logic.

What Tools and Techniques Are Used to Build a Favicon Website?

The build process starts with a standard static website — HTML, CSS, and JavaScript files. These files are concatenated and minified to reduce their total size. Tools like html-minifier, clean-css, and terser handle the minification. The output is a single HTML document with all assets inlined. No external requests, no dependencies.

Next, the minified HTML is base64-encoded. Base64 increases the payload size by approximately 33%, but it ensures the content survives binary transport without corruption. The encoded string is then embedded into an ICO file using a custom script. The script constructs a valid ICO header, adds a minimal PNG image (often just a 1×1 transparent pixel), and appends the base64 payload in the unused space after the image data.

The server configuration is the final piece. A web server — nginx, Apache, or a simple Node.js script — intercepts requests to /favicon.ico and serves the crafted ICO file. The Content-Type header is set to image/x-icon, which satisfies the browser’s expectations. When the browser processes the response, it renders the tiny icon and silently stores the full payload in its cache. A companion script or browser extension can then extract and render the hidden website from the cached favicon data.

ComponentSize (Typical)Purpose
ICO Header6 bytesIdentifies file as ICO format
Image Directory16 bytes/entryDescribes embedded images
Minimal PNG Image~70 bytesValid icon for browser rendering
Base64 HTML Payload5–40 KBThe actual website content
Total File Size5–50 KBWell within browser tolerance

The technique proves that even the smallest, most overlooked corners of web infrastructure can carry meaningful data. Favicons are everywhere. Every site has one. Every browser requests one. And almost nobody inspects what is actually inside them.

How Does the Browser Handle a Favicon-Based Website?

The browser treats a favicon request like any other HTTP resource, but the payload travels through an unexpected channel. According to the source article, the favicon file itself contains the full HTML, CSS, and JavaScript needed to render a functional page (Wehrle, 2025). When the browser requests /favicon.ico, the server responds with encoded website data instead of a traditional icon image.

The trick relies on JavaScript executing after the favicon loads. The script extracts the HTML content from the favicon binary data and writes it into the document using document.write() or DOM manipulation. This approach bypasses conventional rendering entirely.

So the browser never fetches a separate HTML file. Everything ships inside a single .ico request. The page then assembles itself client-side.

From a technical standpoint, this works because browsers do not validate that favicon files contain actual icon data. The browser simply accepts whatever bytes arrive at the /favicon.ico path and passes them to whatever JavaScript processes them. This permissive behavior enables the entire technique.

What Are the Practical Limitations of This Approach?

The favicon storage method faces hard technical constraints that make it unsuitable for production use. The source article notes that favicons typically max out around a few kilobytes, which means complex websites with large images or extensive JavaScript cannot fit (Wehrle, 2025). A single high-resolution photograph could easily exceed the entire storage budget.

Additionally, search engine crawlers cannot execute the JavaScript required to unpack the favicon payload. Googlebot and other indexers would see an empty page with no readable content. This eliminates any possibility of SEO.

The method also breaks when users disable JavaScript. Without script execution, the browser displays nothing — just a blank tab with a favicon. Progressive enhancement strategies do not apply here.

Performance presents another concern. The browser must download the entire favicon, parse its binary contents, extract the HTML, and then render it. This adds processing overhead compared to a standard page load.

Can This Technique Bypass Content Filters or Firewalls?

Content filtering systems typically inspect HTTP response bodies for malicious patterns or blocked keywords. A favicon-based website could theoretically evade simple pattern-matching filters because the HTML content sits encoded within a binary file structure. The filter sees an .ico file, not HTML text.

However, modern enterprise firewalls and deep packet inspection tools examine traffic behavior, not just file extensions. A favicon response returning 50 KB of data would trigger alerts. Normal favicons range from 316 bytes to 4 KB.

The source article does not claim this technique defeats security systems (Wehrle, 2025). The project remains an experimental proof-of-concept exploring unconventional storage. No security bypass was demonstrated or intended.

Network administrators who block arbitrary file types or enforce strict content policies would still catch unusual favicon behavior. The technique works only against naive filtering that trusts file extensions blindly.

What Does This Mean for Web Standards and Browser Security?

This favicon experiment highlights how browsers trust file extensions and content-type headers more than actual file contents. The browser accepts HTML data disguised as an icon without complaint. This permissiveness raises questions about content validation.

The Web Application Security Consortium has noted similar patterns where browsers process mismatched MIME types. The favicon trick exploits this same flexibility. Browsers prioritize rendering over strict validation.

However, no major browser vendor has proposed changes in response to this specific technique. The method requires JavaScript execution and server-side cooperation. It cannot run autonomously or compromise a browser sandbox.

The broader lesson involves understanding how web technologies interact in unexpected ways. Developers building content security policies should consider that any HTTP endpoint can return arbitrary data. A favicon endpoint is just another URL.

Frequently Asked Questions

How much data can actually fit inside a favicon?

The source article demonstrates storing a complete website with HTML, CSS, and JavaScript within a favicon file (Wehrle, 2025). Standard favicon sizes typically range from 316 bytes for a minimal 16x16 icon to several kilobytes for larger formats. The exact capacity depends on how much data the browser will accept in a single favicon response, but the technique works with payloads of several kilobytes.

Does storing a website in a favicon affect page load speed?

The favicon-based approach adds overhead because the browser must download the favicon, extract embedded HTML, and render it via JavaScript. The source article describes this as an impractical but functional experiment (Wehrle, 2025). Standard HTML pages load faster because the browser parses them directly without the extraction step.

Will search engines index a website stored inside a favicon?

Search engine crawlers like Googlebot generally cannot execute the JavaScript required to unpack favicon-embedded content. The source article frames this as a creative experiment rather than an SEO strategy (Wehrle, 2025). Pages delivered through this method appear as empty documents to most indexing bots.

Is this favicon technique useful for anything beyond experimentation?

The source article explicitly describes the project as impractical and not useful for real applications (Wehrle, 2025). The author previously stored two bytes inside a mouse DPI register, demonstrating a pattern of exploring unconventional data storage. These experiments reveal how permissive browser behavior can be repurposed in unexpected ways.

Summary

  • Favicons can carry full websites — browsers accept HTML, CSS, and JavaScript payloads disguised as icon files, rendering them through client-side extraction (Wehrle, 2025).

  • The technique remains experimental — file size constraints, JavaScript dependency, and zero SEO capability make this approach unsuitable for production environments.

  • Content validation is surprisingly permissive — browsers trust file extensions and content-type headers without deeply inspecting whether the data matches the expected format.

  • Security implications are limited but interesting — while this method cannot bypass modern firewalls or compromise browser sandboxes, it demonstrates how standard web protocols can be repurposed in unconventional ways.

  • The real value is conceptual — understanding how browsers process requests and responses helps developers think critically about content security policies and the flexibility of web standards.

If you found this exploration of unconventional web storage interesting, check out the original writeup at timwehrle.de for the full technical details.