Developer documentation
The HeyMadeFonts CSS API serves our open-source fonts from simple css2 URLs, from https://fonts.heymadefonts.com. No API key, no account, no cookies.
Quick start
Add this to the <head> of your page. It is a working snippet for Bade Text, which is in the live catalogue:
<link rel="preconnect" href="https://fonts.heymadefonts.com" crossorigin>
<link href="https://fonts.heymadefonts.com/css2?family=Bade+Text:wght@400;700&display=swap" rel="stylesheet">
body {
font-family: 'Bade Text', sans-serif;
}
Switching from another font service? Change the stylesheet host to fonts.heymadefonts.com and the family names to ours. The switch tool suggests the closest family and writes the new URL. Every family page in the library builds a snippet for the styles you pick.
Endpoints
| Endpoint | Returns |
|---|---|
GET https://fonts.heymadefonts.com/css2?family=… | @font-face CSS (css2 syntax) |
GET https://fonts.heymadefonts.com/css?family=… | @font-face CSS (legacy css syntax) |
GET https://fonts.heymadefonts.com/files/{sha256}.woff2 | Font file, content-addressed and immutable |
GET https://fonts.heymadefonts.com/health | JSON with the catalogue version the CDN is serving |
https://heymadefonts.com/api/v1/… | JSON metadata, downloads, scans and migration; see the JSON API reference |
Compatibility matrix
We publish exactly what we support rather than claim full parity. Anything not listed here is rejected with an error, never approximated.
| Feature | Status | Notes |
|---|---|---|
css2?family=Name | Supported | Regular 400. Spaces as + or %20. Family names are matched case-insensitively. |
css2 wght@400;700 | Supported | Weights 1–1000 that exist in the family. |
css2 ital,wght@0,400;1,700 | Supported | ital is 0 or 1. |
css2 ranges [email protected] | Supported | Variable families only; must lie within the font’s axis. |
css2 wdth | Supported | Point or range; emitted as font-stretch. |
Other axes (opsz, slnt, GRAD …) | Ranges only | Request a range within the axis; set values with font-variation-settings. Pinning a single value returns 422. |
css?family=A:400,700italic|B | Supported | v1 numeric weights, i/italic suffixes and words such as bold, regular, bolditalic. |
display= | Supported | auto, block, swap, fallback, optional. |
| Several families | Supported | Repeat family= (css2) or separate with | (css). Up to 20 families. |
subset= | Ignored | Every subset is served as a unicode-range slice; browsers fetch only what a page uses. |
text= | Not supported | Returns 422. Remove it; slices keep downloads small. |
effect= | Not supported | Returns 422. |
Other parameters (for example WordPress’s ver=) | Rejected | Returns 400 so typos do not go unnoticed. In WordPress, enqueue with a null version. |
| Family or style not in the catalogue | Error | Returns 400 with a CSS comment that names what is missing. We never substitute another family or weight. |
Errors are delivered as a stylesheet so they are visible in the browser’s network panel, for example:
/* HeyMadeFonts FONT_NOT_FOUND: Font family "Example Sans" is not in the HeyMadeFonts catalogue. */
Caching
- Stylesheets (
/css,/css2):Cache-Control: public, max-age=86400, stale-while-revalidate=604800. A new catalogue version reaches cached pages within a day. - Font files (
/files/…):Cache-Control: public, max-age=31536000, immutable. The file name is the SHA-256 of its content, so a file never changes under the same URL. - Client errors are cached for 5 minutes; server errors are not cached.
Cookies, CORS and logging
- The CDN sets no cookies and ignores any it receives.
- Every response carries
Access-Control-Allow-Origin: *, so fonts load from any origin without credentials. - Generated CSS contains nothing derived from the visitor’s request. What the servers log, and for how long, is described in the privacy notice.
Content Security Policy
If your site sends a CSP header, allow the CDN for stylesheets and fonts:
Content-Security-Policy: font-src https://fonts.heymadefonts.com; style-src 'self' https://fonts.heymadefonts.com
Merge these sources into your existing directives rather than replacing them. If you use @import inside your own stylesheet, style-src still needs the CDN.
Troubleshooting
- The font does not appear and the console mentions “mixed content”
- Your page is served over HTTPS but the stylesheet URL starts with
http://. Use thehttps://URL exactly as shown on the font page. - The console reports a CORS error for a .woff2 file
- Fonts are always fetched in CORS mode. Our responses allow every origin, so this usually means a proxy, browser extension or your own server rewrote the response. Check the response headers of the font file in the network panel. For self-hosted fonts on another domain, send
Access-Control-Allow-Originyourself. - The console reports a CSP violation
- Add the CDN to
font-srcandstyle-srcas shown above. - The stylesheet returns 400 or 422
- Open the stylesheet URL in a browser tab: the response is a single CSS comment that says what is wrong, such as a weight the family does not have or an unsupported parameter.
- Text shows in a fallback font for a moment
- That is
display=swapworking as intended. Usedisplay=optionalif you prefer no swap on slow connections, and add thepreconnectline to start the connection earlier.
Limits and fair use
Query strings are limited to 4,096 characters, 20 families and 64 styles per family. The service is free; the terms describe fair use and availability. Current health is on the status page.