Embedding webfonts as data URL

The usual method to embed webfonts is to specify the file for the respective font style. Also see my older article about webfonts.

Generally this works in practice but there are also disadvantages, especially when using multiple font styles.

Note: the following text does not apply to servers and browsers using HTTP/2 (which is the standard protocol for most sites nowadays). In this case most HTTP requests will be in parallel anyway and it might not be worth the trouble embedding fonts as data URL.

The problem with many HTTP requests

A major factor for the duration of loading a web site besides the amount of data is the number of neccessary HTTP requests. Each request causes an additional delay which can barely reduced with fast connections.

Any embedded web font has to be requested by the browser. This means that even for a single font with four styles there are at least four additional requests neccessary.

If you assume that executing a single HTTP request will require about 100 ms you may need additional 400 ms in extreme cases plus the time for transferring the data until the whole loading procedure is finished. Usually requests are parallelized by all common browsers so that in most cases 3 or 4 requests are handled simultaneously – anway this still means additional 100-200 ms as loading fonts will first start after the browser has loaded the stylesheet and intepreted the indications in it to load the fonts.

An example:

On my website I use the font “Lato” with four styles. This font requires 182 KiB in total, distributed among four files.

If you assume a transfer speed of 500 KiB per second, which is realistic using DSL 6000 or a good UMTS/LTE connection, the sole transfer of this amount of data requires 364 ms calculative. There is also time needed for the HTTP requests which means at least 200-400 ms additionally. This means that just requesting the fonts from the server takes nearly the same time or even longer than just transferring the data. In combination with HTTPS this even gets worse as there is more time needed to establish a connection.

Well – you could question if half a second more or less time required to load something is really that important. But in practise not all HTTP requests are always handled as fast as the connection speed allows. Depending on the browser there is an additional issue which particularly gets visible on slow connections with high latency (for example on mobile devices with limited network connection): the browser loads the document and the stylesheets and then immediatly starts to display it with the available fonts on the device. The webfonts to be used will then be requested in the background and the display will be updated as soon as the webfont has been transferred. This may take a couple of seconds and may also happen multiple times (for each single font style) which is at least quite irritating.

The solution using a data URL

A “data URL” (or data URI) is an URL scheme which allows to include data directly in an URL without referring an external resource. The scheme had already been specified in 1998 and the method works with all common browsers. Also see the RFC 2397 and http://caniuse.com/#search=dataurl.

For binary data it looks simplified like the following:

data:<MIME type>;base64,<data coded as base64>

As an example a picture using a data URL (shortened for better readability):

<img alt="Globus" src="data:image/png;base64,iVBORw0KGgo ... " />

In the same way you can use data URLs also in stylesheets (again shortened):

.myclass {
  background-image: url(data:image/png;base64,iVBORw0KGgo ... );

The biggest advantage is that an additional HTTP request is not required any longer to load the picture but the data is already included in the HTML document or in the stylesheet. For smaller pictures which contain less than 1 KiB of data this method generally makes sense as more time is required for the HTTP request as for the data transfer.

URLs have a length limitation. But up to 64 KiB should generally not be a problem with newer versions of Firefox, Safari, Chrome, Internet Explorer or Opera and the respective mobile versions.

Therefore you can use the same method as for pictures also for webfonts – here shown with the font “Lato” as mentioned earlier where every single style requires less than 64 KiB even as base64 (shortened for better readability).

A note about the format: providing just WOFF (Web Open Font Format) will cover most of the current browsers, as even Internet Explorer and Android browsers or iOS nowadays support WOFF as well and don’t require EOT or TTF any longer.

@font-face {
    font-family: "Lato";
    src: url(data:font/woff;base64,d09GRgABAAAAALQ ... ) format("woff");

@font-face {
    font-family: "Lato"; 
    font-style: italic;
    src: url(data:font/woff;base64,d09GRgABAAAAALh ... ) format("woff");

@font-face {
    font-family: "Lato";
    font-style: normal;
    font-weight: bold; 
    src: url(data:font/woff;base64,d09GRgABAAAAALR ... ) format("woff");

@font-face {
    font-family: "Lato";
    font-style: italic;
    font-weight: bold;
    src: url(data:font/woff;base64,d09GRgABAAAAALm ... ) format("woff");

The stylesheet will become about 240 KiB larger since the fonts encoded as base64 require about 30% more space. Though it is possible to reduce this a lot by using gzip compression (for example by using the deflate module in Apache), so at the end the amount of data to be transferred is just a little more than before with the stylesheet and four separate webfonts.

In any case the four additional HTTP requests are not needed any longer. Even when taking into account that loding the stylesheets takes longer due to its size, the whole loading process is still faster.

Before this measure there where about 21 requests needed to load the start page and loading the webfonts sometimes started not before 1 to 1.5 seconds after the first request. The whole loading process took about 2-3 seconds depening on the general conditions.

After the change as described above there are only 15 requests (I also modified some pictures to be embedded as data URL as well) and the whole loading process has been speed up significantly: under ideal conditions even with empty cache it takes barely longer than a second, but it is generelly faster than before, especially on slower connections where each additional request causes significant delays.

Converting webfonts into base64

A very simple solution to create the base64 data is http://dataurl.net/#dataurlmaker. Here you can drag the respective file into the field “Drag file here” using drag & drop or select it from your local harddisc using “Browse…”. You then immediately get the base64 version of it in a text area from which you can copy it to the clipboard:


You should only remember to replace “application/octet-stream” by the value “font/woff” before putting the data into a stylesheet. Also the length of the data URL should not exceed 65536 bytes (equivalent of 64 KiB).

Limitations of data URLs

Besides the already mentioned maximum length of data URLs another aspect should be considered as well.  The considerations about embedding of webfonts assume that the fonts (or the picture as shown in the example) are all getting used. Only then this method provides an advantage.


If a stylesheet defines many external resources the general conversion to data URLs may have a negative result as the sole data transfer of the larger stylesheet takes more time than the single requests which occured before. Browsers usually only request those elements which they actually need. If you define 50 rules pictures in your stylesheet but the actual document only uses four of them, browsers will also only request those four pictures and not all the 50. Depending on the amount of data it may therefore still be wise to embed the pictures using external URLs.

Leave a public comment

Your email address will not be published. This is not a contact form! If you want to send me a personal message, use my e-mail address in the imprint.

You can use the following HTML tags in the comment:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>