Data URI size calculator
Know how long a data URI will be before you encode anything: a 1024-byte PNG becomes 1390 characters, which still fits the default 2048-character budget, so inlining is recommended. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Bytes
- 1,024
- Media type
- image/png
- Prefix chars
- 22
- Base64 chars
- 1,368
- Padding chars
- 2
- Data uri chars
- 1,390
Teams that search for a data URI size calculator usually already know the original file size and need the encoded length before they bake the string into HTML, CSS, or an email. This tool accepts the original size in bytes, an optional MIME type for the RFC 2397 prefix, and an optional inlining budget.
How Base64 data URI size is computed from original bytes
Remainder one needs two pads, remainder two needs one pad, and remainder zero needs none. The prefix is the literal characters data-colon, plus the MIME type you supply, plus semicolon-base64-comma. For image/png that prefix is twenty-two characters; for application/octet-stream it is thirty-seven; for image/svg+xml it is twenty-six.
The total data URI length in characters is prefix length plus Base64 length. Because the Base64 alphabet and the prefix are ASCII, that character count equals the UTF-8 byte count of the URI string. Adding the prefix lifts the total overhead above that floor, which is why a twenty-four-byte favicon and a twenty-four-kilobyte stylesheet do not inflate by the same percentage.
This calculator applies those identities to the original byte size without reading the file, so you can decide whether inlining is worthwhile before you encode a single octet.
When inlining a data URI is worth the thirty-three percent overhead
The usual reason to inline is to save a request: a tiny PNG icon, a WOFF2 subset, or a few hundred bytes of critical CSS can cost more in latency and connection setup than they cost as extra HTML or CSS bytes. A practical default is two kilobytes of data URI: under that budget, inlining an icon in a component or an email template is often still a win; above it, serve the file and let the browser cache it.
Email HTML is a special case: many clients block remote images until the reader clicks, so embedding a logo as a data URI can be worth a larger budget even after the thirty-three percent tax. Fonts inlined in CSS block first paint if the sheet is large, so measure the encoded size before you paste a whole family into a style tag. Failed validation does not consume balance.
What you can do with it
Bundler and design-system inlining budgets
Feed webpack, Vite, or a design-system pipeline the file size of an icon or font and fail the build when the encoded data URI would exceed the agreed budget.
HTML email logos and signatures
Estimate how large an embedded logo will be after Base64 so the message stays under client size caps and still displays without a remote image fetch.
Critical CSS and icon sheets
Compare the encoded size of a small SVG or CSS snippet against a 2 KiB or 8 KiB inline budget before pasting it into a document head.
FAQ
How do I calculate data URI size from the original file size?
Send the original size as bytes (a positive integer).
Why is Base64 data URI overhead about 33 percent?
The data: prefix adds a few extra characters on top.
Does the MIME type change the encoded size?
Only the prefix. image/png uses 22 prefix characters; application/octet-stream uses 37.
What does the data URI size calculator cost?
The browser tool is free. No file is uploaded or encoded.
When is it worth inlining a file as a data URI?
Usually for small assets such as an icon, a font subset or a few hundred bytes of critical CSS, where saving a separate download matters more than the extra bytes. Under the default budget the tool recommends inlining; above it, keep a file the browser can cache.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/data-uri-size \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"bytes":1024}'const res = await fetch("https://api.kit.forhosting.com/dev/data-uri-size", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"bytes": 1024
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/data-uri-size",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"bytes": 1024
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/data-uri-size", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"bytes":1024}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"bytes":1024}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/data-uri-size", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"bytes": 1024
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.data_uri_size",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_bytes | 1000000000000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Inlining a font, icon, or stylesheet as a data URI avoids an extra HTTP request, but Base64 encoding inflates the payload by about one third and a data: prefix adds still more characters. It returns the exact Base64 payload length, the full data URI character count, the payload overhead near thirty-three percent, the total overhead including the prefix, and a recommendation to inline or keep a separate link. Successful API calls cost $0.002; invalid input is not billed.
How Base64 data URI size is computed from original bytes
A data URI that carries binary content uses the RFC 2397 form data, then an optional media type, then the token semicolon-base64, then a comma, then the payload. The payload is standard RFC 4648 Base64: every three original bytes become four ASCII characters, so the encoded length is exactly four times the ceiling of the original length divided by three. When the original length is not a multiple of three, padding equals signs fill the last quartet so the payload length is always a multiple of four. Payload-only overhead is therefore about thirty-three percent—exactly one third when the original size is a multiple of three, and a little more when padding is required.
Input contract, response shape, and error behaviour
Ten thousand bytes as the default octet-stream type yields a 13373-character URI and a link recommendation. POST a JSON body with one required field bytes: a positive integer (or numeric string) for the original asset size before encoding. Aliases size, length, n, and byte_count map to the same parameter so bundler scripts and form widgets can keep their local names. Optional media_type (aliases mime, type, content_type, mime_type) is the MIME type written into the prefix; it defaults to application/octet-stream when omitted. Optional budget (aliases max, limit, max_bytes, max_size) is the largest data URI length you still treat as worth inlining and defaults to 2048, a common HTTP/1 rule of thumb. Missing, empty, non-integer, zero, or negative values fail with invalid_input naming the field; a media type that is not type/subtype, or that contains whitespace or a comma, is rejected the same way. Those failures are not billed. On success the body echoes bytes, media_type, and budget; returns prefix and prefix_chars; returns base64_chars and padding_chars; returns data_uri_chars and overhead_chars; returns overhead_percent for the full URI versus the original file and payload_overhead_percent for the Base64 payload alone (the roughly thirty-three percent figure); returns expansion_ratio as data URI length over original bytes; and returns within_budget plus recommendation set to inline or link. Example: 1024 bytes as image/png yields a 22-character prefix, 1368 Base64 characters with two pads, a 1390-character data URI, payload overhead about 33.59 percent, and an inline recommendation against the default 2048 budget. Pair the numbers with your own encoder if you need the string itself; this endpoint never emits the encoded payload.
When inlining a data URI is worth the thirty-three percent overhead
Base64 makes that trade-off worse by about one third, and HTTP/2 or HTTP/3 multiplexing makes a separate request cheaper than it was on HTTP/1, so the break-even size is smaller than many 2012-era blog posts still claim. Bundlers that used an eight-kilobyte url-loader limit were optimizing for HTTP/1 sprites; override budget to 8192 if you are matching that legacy rule, or lower it for HTTP/2 sites. Use it as a gate in a pull-request check: if data_uri_chars exceeds the budget, keep the asset as a URL.
Technical questions
When should I inline an asset as a data URI?
When data_uri_chars is within your budget (default 2048). Below that, avoiding a request often wins; above it, keep a cacheable URL—especially on HTTP/2. Override budget to match your bundler limit.