The quick download
On mobile, data URIs rendered up to 6x slower than source-linked binary images.
-
Base64 encoding forces the browser to decode inline data on every render, burning CPU and battery on lower-powered phones.
-
Inline images cannot be cached on their own, so they reload whenever their parent HTML or CSS changes.
-
HTTP/2 and HTTP/3 multiplexing have erased most of the request savings that made data URIs attractive.
-
Reserve data URIs for tiny, single-use assets critical to first paint, and validate every choice with real user and synthetic data.
Small frontend decisions shape how fast your pages load, how much CPU and battery mobile devices burn, and whether users stay or leave. How you serve images, scripts, and styles can be the difference between a snappy experience and a sluggish one, especially on mobile networks and lower-end hardware.
Data URIs were widely recommended for years because fewer HTTP requests were assumed to mean faster pages. But in a 2013 Real User Monitoring experiment originally run by Peter McLachlan, then Chief Architect at Mobify, the results told a different story. Catchpoint later republished McLachlan’s findings, which still carry a useful lesson for modern observability teams: performance decisions should be validated with real user and synthetic data, not assumed from best practices alone.
This article covers how data URIs work, what the original experiment found, what has changed since 2013, and how to decide whether inline images help or hurt your performance today.
What Is a Data URI?
The data URI scheme (defined in RFC 2397) lets you embed file data directly in HTML or CSS using base64 encoding. Instead of referencing an external file that requires a separate HTTP request, the browser reads the asset’s content inline from the document itself.
The format looks like this:
data:[mediatype];base64,[encoded data]
For example, a small PNG might appear as an img tag with a src attribute containing the full base64-encoded image data. The browser decodes it in place without making a network request.
The Hidden Costs of Data URIs
Eliminating an HTTP request sounds like a clear win. In practice, data URIs introduce four costs that are easy to overlook:
- Transfer size. Base64 encoding makes data roughly 1.37x larger than its binary equivalent. Gzip compression reduces this gap to about 3% overhead, so raw size is actually the smallest concern.
- CPU decode cost. The browser must decode base64 back to binary before it can use the image. On mobile devices, this consumes CPU cycles and battery, with measurable impact on lower-powered hardware.
- No independent caching. If the data URI lives in HTML or uncached CSS, it gets re-downloaded with every page request. Even in cached CSS, the asset can’t be cached separately from the stylesheet, so any change to that stylesheet invalidates the image too.
- Repeated materialization overhead. The base64-to-binary conversion can create repeated materialization overhead across renders. Unlike a separately cached binary image (which the browser can store in decoded form in memory), data URIs impose this decode cost each time the page renders.
Binary images still require image decoding (JPEG or PNG decompression), but they skip the additional base64 decode step and benefit from independent HTTP caching. The browser can also store decoded binary images in memory for reuse across renders, avoiding redundant work.

What the Original Mobify Experiment Found
Peter McLachlan, then Chief Architect at Mobify, ran a Real User Monitoring test across 436 active mobile websites with approximately 230,000 trials. The test compared materializing a cached 17.8kB PNG via binary src versus a data URI, measuring time for five materializations per trial.

Results
The original results visualized the difference clearly: data URI materialization took longer on average and showed much wider variance than binary image materialization across the tested mobile platforms.

| Platform | Binary src (5 materializations) | Data URI (5 materializations) | Data URI overhead |
| iOS 6 | ~32ms | ~200ms | ~6x slower |
| Android 4.2 | ~55ms | ~330ms | ~6x slower |
| Android 2.2 | ~180ms | ~1,800ms | ~10x slower |
On iOS 6 and Android 4.2, binary image materialization was about 6x faster. On older hardware (Android 2.2), it was up to 10x faster, with data URI materialization taking nearly 2 seconds for five images.
Variance
Standard deviation was significantly higher for data URIs, meaning performance was less predictable. This effect was most pronounced on lower-end devices, where available CPU fluctuates more depending on background processes and system load.




Binary vs. Data URI Comparison
| Factor | Binary src | Data URI |
| Network request | Required (mitigated by HTTP/2+ multiplexing) | None (image is inline) |
| Base64 decode | No base64 decode step; standard image decoding still applies but benefits from browser caching and memory storage. | Can add repeated materialization overhead |
| Independent caching | Yes (standard HTTP cache headers) | No (locked to parent file) |
| Transfer size | Original binary size | 37% larger before gzip (3% after) |
| Render performance | Faster, more predictable | Slower, higher variance |
What Has Changed Since 2013
The web platform has shifted substantially since this experiment ran. Several changes affect how we should think about data URIs today.
HTTP/2 and HTTP/3 Multiplexing
The original “reduce HTTP requests” rule was driven by HTTP/1.1’s connection limits (typically six connections per domain). With HTTP/2 and HTTP/3, multiplexed connections handle many requests over a single connection with minimal overhead. The primary motivation for data URIs (avoiding request cost) has weakened significantly.
Modern Browser Caching and Resource Hints
Browsers now support preload, preconnect, and more sophisticated cache strategies. Separately cached assets benefit from these optimizations. Inline data URIs do not, because they’re locked inside their parent document or stylesheet.
Mobile Hardware
Today’s devices have far more CPU headroom than 2013-era phones. The base64 decode penalty still exists, but it’s less dramatic on current hardware. That said, low-end devices still matter globally, and the performance gap between high-end and budget hardware remains wide.
Core Web Vitals
Google’s performance metrics (LCP, CLS, INP) reward fast, stable rendering. Large data URIs embedded in critical CSS can delay First Contentful Paint by bloating render-blocking stylesheets. This makes inline encoding counterproductive for anything beyond tiny assets.
SVG and Icon Systems
Many use cases that once called for data URIs (small icons, UI elements) are now better served by inline SVG, icon fonts, or SVG sprite sheets. These approaches avoid base64 overhead entirely while offering better scalability and styling control.
The Bottom Line on What Changed
The tradeoff is no longer “HTTP request vs. no request.” It’s about cacheability, critical rendering path impact, payload size, CPU decode cost, and long-term maintainability. Each of these factors deserves consideration when you’re choosing how to serve assets.
How to Decide Today
Work through these questions before choosing a data URI over a standard cached asset:
- Is the asset tiny (under 2-3kB encoded)?
- Is it used on only one or two pages (not reused across the site)?
- Does it need to load with the very first paint, with no extra request tolerable?
- Is the parent HTML or CSS file already well-cached?
- Would a separate cached image, SVG, or sprite serve equally well?
- Have you tested the actual impact with real user data?
If the asset is small, single-use, and critical to first paint, a data URI may still be the right call. For everything else, prefer independently cacheable assets that benefit from browser caching, memory storage, and modern delivery optimizations.
Validate With Real Performance Data
The original experiment’s strongest lesson is that a “best practice” failed under measurement. Teams assumed data URIs were faster because they eliminated requests. Real user data showed the opposite on the hardware that mattered most.
This is why measurement matters more than assumptions. Real User Monitoring, synthetic testing (including tools like WebPageTest), and field performance data let you validate frontend decisions against actual user experience. You can see whether a change helps the users you care about, on the devices they actually use, under real network conditions.
Performance intuition is unreliable, especially at the intersection of encoding, caching, and rendering. The teams that get this right are the ones who test before and after, then keep watching.
Recommendations
- Use data URIs sparingly: for tiny (under 2-3kB), critical, non-reused assets where eliminating a request genuinely helps first paint.
- Prefer independently cacheable assets for reusable UI elements: standard image files, CSS sprites, SVG sprites, or inline SVG.
- Test with real user and synthetic data before and after changes. Performance intuition is unreliable, especially at the intersection of encoding, caching, and rendering.
- With HTTP/2 and HTTP/3, the “avoid every request” rule is less relevant. Focus instead on cacheability, rendering path, and actual measured impact.
Validate your front-end performance choices with real user and synthetic data.
LogicMonitor delivers real user monitoring, synthetic testing, and full-stack observability in one view. See how your pages perform on the devices and networks your users actually rely on.
FAQs
Are data URIs always slower than linked images?
No. For tiny, single-use assets that must load with the first paint, a data URI can still help by removing one request. The original testing showed the penalty grows with image size and repeated rendering, and it hits hardest on lower-end mobile hardware.
Why does base64 encoding hurt performance?
Base64 makes the data about 37% larger before compression and, more importantly, forces the browser to decode it back to binary before display. That decode step consumes CPU and battery on every render, and inline data cannot be cached independently of its parent file.
Does HTTP/2 change whether I should use data URIs?
Yes. HTTP/1.1 limited each domain to about six connections, which made cutting requests valuable. HTTP/2 and HTTP/3 multiplex many requests over one connection, so the main reason to inline images has largely disappeared. Cacheability and rendering impact now matter more.
Denton Chikura is a technical writer and longtime observability advocate focused on helping site reliability engineers and engineering teams discover the tools and capabilities that strengthen internet resilience. He works at the intersection of monitoring, performance, and infrastructure to make complex systems more understandable and usable, bridging the gap between deep technical detail and real‑world operations. His goal is to help teams build faster, detect issues earlier, and recover smarter, ultimately making the internet a better, more reliable place for everyone.
Disclaimer: The views expressed on this blog are those of the author and do not necessarily reflect the views of LogicMonitor or its affiliates.




