Convert SVG to data URI for CSS
Paste SVG markup and get a data URI that starts with data:image/svg+xml, ready for a CSS url() or an image source. A color such as #0a7 becomes %230a7, so no character can break your stylesheet. Malformed markup is refused. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Turn raw SVG markup into a compact data URI that can be placed in a CSS url() value or used wherever an image URL is accepted. The converter first checks that the input is well-formed XML, then encodes the document as UTF-8 and escapes every character that could change URL or CSS parsing. The result starts with the SVG media type and contains no base64 layer, making it straightforward to inspect, copy, cache, and version alongside your styles.
Why SVG data URIs need deliberate escaping
An SVG is text, but pasting that text directly into a CSS <code>url()</code> token is unreliable. A color such as <code>#0a7</code> introduces a URL fragment, whitespace can split tokens, and quotes or parentheses can end the surrounding CSS value. This converter avoids those ambiguities by encoding the SVG as UTF-8 bytes and leaving only URL unreserved characters readable.
Everything else becomes a percent escape, including hashes, angle brackets, quotation marks, apostrophes, parentheses, spaces, and line breaks. The returned value therefore remains intact whether you place it in an unquoted <code>url(...)</code>, a single-quoted value, or a double-quoted value. The media prefix is <code>data:image/svg+xml,</code>, followed by the encoded markup.
There is no base64 step, so common letters and numbers stay visible and the result is usually easier to audit in a stylesheet.
Validation happens before conversion
Encoding malformed markup would produce a perfectly escaped value that still fails when a browser tries to parse the image. To prevent that misleading result, the converter checks the XML document first. It requires one SVG root element, properly nested and matching opening and closing tags, quoted attribute values, unique attribute names on each element, closed comments and CDATA sections, and valid entity references.
Text outside the root and a second root element are rejected. XML declarations, processing instructions, comments, CDATA, and a document type declaration are accepted when they appear in structurally valid positions. Preview the finished image in the browsers you target when compatibility matters.
Using the result in CSS and HTML
Use the returned URI anywhere the platform expects an image URL. In CSS, a typical destination is <code>background-image</code>, a mask source, a list marker, or generated content. You can wrap the value in either kind of quote for readability, although the strict escaping also protects an unquoted <code>url()</code> token.
In HTML, it can be assigned to an image <code>src</code> attribute after normal HTML attribute quoting. Keep in mind that data URIs duplicate their bytes at every occurrence unless your build system extracts or reuses the declaration, so they are best for small icons, badges, and decorative artwork rather than large illustrations. The conversion is deterministic: identical input produces identical output, which makes the result suitable for snapshots, generated stylesheets, and content-addressed build artifacts.
The converter does not fetch referenced fonts, images, or styles, does not optimize paths, and does not sanitize active SVG content. Treat markup from an untrusted party according to the security rules of the place where you will embed it.
What you can do with it
Inline a small CSS icon
Convert a checked-in SVG asset into a safe background-image value without adding a separate network request.
Generate theme-aware styles
Encode SVG variants during a build and place the deterministic URIs in design-token or component stylesheets.
Verify generated SVG markup
Reject broken XML from a template pipeline before publishing the encoded image string to a site or application.
FAQ
Why is the SVG percent-encoded instead of base64-encoded?
SVG is already text. Percent encoding avoids an extra base64 layer, keeps unreserved characters readable, and produces a standards-compatible image data URI.
Does the converter optimize or sanitize the SVG?
No. It validates XML structure and encodes the original markup exactly; it does not remove metadata, scripts, external references, or redundant path data.
Can I paste the result straight into a CSS url()?
Yes. Every character that could end or split a CSS value, including quotes, parentheses, spaces and hash signs, is escaped, so the value works unquoted, in single quotes or in double quotes. Copy the whole string, including the data:image/svg+xml, prefix.
Why was my SVG rejected?
Because the markup is not well-formed. A tag is not closed or nested correctly, an attribute is unquoted or repeated, a comment is left open, an entity is invalid, or there is text or a second element outside the single svg root.
When is a data URI a poor choice for an SVG?
When the image is large or used in many places. A data URI repeats all of its bytes wherever it appears, so it suits small icons, badges and decorative artwork far better than big illustrations.
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/web/svg-to-data-uri \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#0a7\" d=\"M2 2h20v20H2z\"/></svg>"}'const res = await fetch("https://api.kit.forhosting.com/web/svg-to-data-uri", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#0a7\" d=\"M2 2h20v20H2z\"/></svg>"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/svg-to-data-uri",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#0a7\" d=\"M2 2h20v20H2z\"/></svg>"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/svg-to-data-uri", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"svg":"<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\"><path fill=\\"#0a7\\" d=\\"M2 2h20v20H2z\\"/></svg>"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#0a7\" d=\"M2 2h20v20H2z\"/></svg>"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/svg-to-data-uri", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path fill=\"#0a7\" d=\"M2 2h20v20H2z\"/></svg>"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.svg_to_data_uri",
"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
timeout_sec | 30 |
max_crawl_pages | 25 |
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
Why SVG data URIs need deliberate escaping
Copy the complete returned string, not just the encoded portion, because the media prefix tells browsers how to interpret the payload.
Validation happens before conversion
If validation fails, the request returns an <code>invalid_input</code> error with a description of the structural problem instead of a data URI. This is XML validation rather than visual SVG validation: it confirms that the markup is syntactically well formed, but it does not promise that every SVG element, attribute, paint value, animation, or external reference is supported by every browser.
Technical questions
What does the API conversion cost?
Each API request costs $0.002. The browser version can run locally on this page.
Can I paste the result directly inside CSS url()?
Yes. Quotes, parentheses, whitespace, hashes, and other parsing-sensitive characters in the SVG payload are percent-encoded.
What happens when the XML is malformed?
The conversion stops and returns an invalid_input error describing the malformed structure. No partial data URI is returned.