Fonts API

Fonts API

Public REST API for searching, downloading and embedding our open-source font library. Compatible with the Google Fonts CSS2 syntax.

A free, public REST API to search, inspect and embed our open-source font library. Compatible with the Google Fonts CSS2 syntax — drop in a tag and you are done.

<!-- Embed a font in your page -->
<link rel="stylesheet" href="https://jinero.online/api/v1/fonts/css?family=Inter:wght@400,700&display=swap">

<style>
  body { font-family: "Inter", system-ui, sans-serif; }
</style>
// Search fonts
const r = await fetch("https://jinero.online/api/v1/fonts?name=mono&per_page=10");
const { data } = await r.json();
console.log(data.map(f => f.name));

All read endpoints are public — no key required. Unauthenticated requests are throttled to 60 requests per minute per IP. Authenticated requests get 600 req/min. Generate a token on your profile page (sign in first) — the plaintext value is shown only once on creation; we only store a SHA-256 hash. Send it as either an Authorization Bearer token or an X-API-Token header.

# Public — no auth, 60 rpm per IP
curl https://jinero.online/api/v1/fonts?name=inter

# X-API-Token header — 600 rpm
curl -H "X-API-Token: YOUR_TOKEN" https://jinero.online/api/v1/user

# Bearer (also accepted)
curl -H "Authorization: Bearer YOUR_TOKEN" https://jinero.online/api/v1/user
// Same token, fetch from the browser
const r = await fetch("https://jinero.online/api/v1/user", {
  headers: { "X-API-Token": "YOUR_TOKEN" },
});
const me = await r.json();
$user = Http::withHeaders(['X-API-Token' => env('JINERO_API_TOKEN')])
    ->get("https://jinero.online/api/v1/user")
    ->json();

Paginated, filterable list of font families. Use this to power a search box, a picker, or pull metadata in bulk.

GET https://jinero.online/api/v1/fonts
ParameterTypeDescription
name string Substring match on family name (case-insensitive).
category string|csv Filter by category: sans, serif, display, handwriting, monospace.
langs csv Required language subsets, e.g. latin,cyrillic.
variable boolean Only variable fonts when true.
monospace boolean Only monospace fonts when true.
styles_min integer Minimum number of weights/styles.
styles_max integer Maximum number of weights/styles.
order string likes (default), downloads, views, name, created_at.
sort string asc or desc (default desc).
per_page integer Page size (max 100, default 48).
page integer Page number (1-based).
curl "https://jinero.online/api/v1/fonts?name=mono&variable=true&per_page=5"
const params = new URLSearchParams({
  name: "mono",
  variable: "true",
  per_page: "5",
});
const r = await fetch(`https://jinero.online/api/v1/fonts?${params}`);
const { data, total } = await r.json();
$r = Http::get("https://jinero.online/api/v1/fonts", [
    "name" => "mono",
    "variable" => "true",
    "per_page" => 5,
]);
$data = $r->json("data");
Example response
{
  "current_page": 1,
  "per_page": 5,
  "total": 23,
  "data": [
    {
      "id": 142,
      "name": "JetBrains Mono",
      "slug": "jetbrains-mono",
      "category": "monospace",
      "variable": true,
      "langs": ["latin","cyrillic"],
      "styles_count": 16,
      "downloads": 4821,
      "regular_url": "/storage/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2"
    }
  ]
}

Full metadata for a single font family — every weight, every italic, every file URL. Also returns ready-made download/files/css URLs.

GET https://jinero.online/api/v1/fonts/{slug}
curl https://jinero.online/api/v1/fonts/inter
const r = await fetch("https://jinero.online/api/v1/fonts/inter");
const family = await r.json();
console.log(family.fonts);
$family = Http::get("https://jinero.online/api/v1/fonts/inter")->json();
Example response
{
  "name": "Inter",
  "slug": "inter",
  "category": "sans",
  "designer": "Rasmus Andersson",
  "license": "OFL",
  "variable": true,
  "styles_count": 18,
  "download_url": "https://jinero.online/api/v1/fonts/inter/download",
  "files_url": "https://jinero.online/api/v1/fonts/inter/files",
  "css_url": "https://jinero.online/api/v1/fonts/css?family=inter",
  "fonts": [
    {
      "weight": 400,
      "italic": false,
      "style_name": "Regular",
      "files": [
        { "format": "woff2", "url": "/storage/fonts/inter/Inter-Regular.woff2", "size": 96241 }
      ]
    }
  ]
}

Flat list of every font file for a family — handy when you want direct URLs to use in your own @font-face rules.

GET https://jinero.online/api/v1/fonts/{slug}/files
curl https://jinero.online/api/v1/fonts/inter/files
const r = await fetch("https://jinero.online/api/v1/fonts/inter/files");
const { files } = await r.json();
Example response
{
  "family": "Inter",
  "slug": "inter",
  "files": [
    { "weight": 400, "italic": false, "style": "Regular", "format": "woff2", "url": "/storage/fonts/inter/Inter-Regular.woff2", "size": 96241 },
    { "weight": 700, "italic": false, "style": "Bold", "format": "woff2", "url": "/storage/fonts/inter/Inter-Bold.woff2", "size": 99812 }
  ]
}

Returns a ZIP archive with all WOFF2 files and a ready-to-use fonts.css. Use this when you want to self-host the family.

GET https://jinero.online/api/v1/fonts/{slug}/download
curl -L -o inter.zip https://jinero.online/api/v1/fonts/inter/download
// Trigger a browser download
window.location.href = "https://jinero.online/api/v1/fonts/inter/download";

Drop-in replacement for the Google Fonts CSS2 API. Loads @font-face rules pointing at our hosted woff2 files. Identical syntax — same family/weight/italic specifiers.

GET https://jinero.online/api/v1/fonts/css
ParameterTypeDescription
family string Family slug, optionally followed by axes. Repeat for multiple families.
display string CSS font-display value: swap (default), auto, block, fallback, optional.
<!-- Simplest form: regular weight only -->
<link rel="stylesheet" href="https://jinero.online/api/v1/fonts/css?family=inter">

<!-- Specific weights -->
<link rel="stylesheet" href="https://jinero.online/api/v1/fonts/css?family=inter:wght@400,500,700&display=swap">

<!-- Italic + weight tuples (Google syntax) -->
<link rel="stylesheet" href="https://jinero.online/api/v1/fonts/css?family=inter:ital,wght@0,400;1,400;0,700">

<!-- Multiple families -->
<link rel="stylesheet" href="https://jinero.online/api/v1/fonts/css?family=inter:wght@400,700&family=jetbrains-mono:wght@400">
/* Returned content */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('https://jinero.online/storage/fonts/inter/Inter-Regular.woff2') format('woff2');
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('https://jinero.online/storage/fonts/inter/Inter-Bold.woff2') format('woff2');
}
Try it live Type a family slug and load it via the CSS endpoint
The quick brown fox jumps over the lazy dog — 0123456789

Identify which font is in a cropped text image. There is no OCR step on our side — you must supply the same characters you see in the image via sample_text. The recognizer uses your text to render reference glyphs per candidate font and score them against your image; without it, accuracy drops sharply. Crop tightly to one line of text for best results.

POST https://jinero.online/api/v1/fonts/recognize
ParameterTypeDescription
image file (multipart) Tight crop of the text. jpg/jpeg/png/webp/bmp, max 8 MB.
sample_text string The actual characters in the image. Optional but strongly recommended — ≤160 chars.
top_k integer Number of matches to return. 3–20, default 8.
curl -X POST https://jinero.online/api/v1/fonts/recognize \
  -F "[email protected]" \
  -F "sample_text=The quick brown fox" \
  -F "top_k=5"
const form = new FormData();
form.append("image", file);
form.append("sample_text", visibleText);   // what your eyes see in the crop
form.append("top_k", "5");

const r = await fetch("https://jinero.online/api/v1/fonts/recognize", { method: "POST", body: form });
const { recognition } = await r.json();
// recognition.matches: [{ slug, name, score, ... }]
$res = Http::attach(
    "image",
    file_get_contents("crop.png"),
    "crop.png"
)->post("https://jinero.online/api/v1/fonts/recognize", [
    "sample_text" => "The quick brown fox",
    "top_k" => 5,
]);
$matches = $res->json("recognition.matches");
Example response
{
  "success": true,
  "sample_text": "The quick brown fox",
  "top_k": 5,
  "recognition": {
    "matches": [
      { "slug": "inter",            "name": "Inter",            "score": 0.92, "category": "sans" },
      { "slug": "manrope",          "name": "Manrope",          "score": 0.88, "category": "sans" },
      { "slug": "plus-jakarta-sans","name": "Plus Jakarta Sans","score": 0.85, "category": "sans" }
    ],
    "method": "glyph-shape",
    "elapsed_ms": 2841
  }
}

Standard HTTP semantics. Errors return a JSON body with a `message` field (or a CSS comment for the /css endpoint).

// 404 — family not found
{ "message": "Font family not found" }

// 422 — validation (oversized image, wrong mime, bad top_k)
{ "message": "Upload a tight crop of the text to analyze." }

// 422 — recognizer index missing on the server
{ "message": "Recognizer index is missing." }

// 429 — rate limit exceeded (recognize = 3 req/min)
{ "message": "Too Many Attempts." }

// 400 — bad request (CSS endpoint, no family)
/* Missing 'family' parameter */

About the jinero.online Fonts API

Public REST API for searching, downloading and embedding our open-source font library — compatible with the Google Fonts CSS2 syntax.

Drop-in CSS

Same URL shape as Google Fonts CSS2 — swap the host and your existing tags keep working.

Open Licenses

Every family ships with its license and designer metadata. Build catalogs, attribution pages and pickers without scraping.

Self-Hosting

Download a ready-to-use ZIP per family — WOFF2 files plus a generated fonts.css. No build step needed.

No Key Required

Public read endpoints are free with a per-IP rate limit. Generate an API token in your profile when you need higher limits.

Frequently Asked Questions

No. All read endpoints (list, show, files, download, css) are public and rate-limited per IP. You only need a token to favorite fonts on behalf of a user or to get a higher rate limit.

The syntax matches Google Fonts CSS2 (family, wght, ital, display). The family identifier is our slug (e.g. "inter", "jetbrains-mono") rather than the display name with a "+" — slugs are returned by the search endpoint.

WOFF2 for the CSS endpoint and most downloads, with TTF fallbacks for single-style downloads. The /fonts/{slug} endpoint returns every available format with size and URL.

Each font family carries its own license (OFL, Apache, etc.). The license and license_url fields on /fonts/{slug} tell you exactly what is permitted. Always check the source license before commercial use.