Skip to main content
The API includes 90 handwriting fonts with varying styles and language support.

Fetching the catalog

curl -sS https://api.handtextai.com/api/v1/fonts \
  -H "Authorization: Bearer htext_YOUR_KEY"
Response:
{
  "fonts": [
    {
      "id": 1,
      "supported_languages": ["en", "fr", "de", "ru", "uk", ...]
    },
    ...
  ]
}

Key points

  • Font IDs are numeric (190)
  • The API does not expose font names (intentional for licensing)
  • Each font has supported_languages (BCP-47 codes)

Reliability notes (important)

For most production use cases, we recommend starting with font IDs 1 or 2. They are the most widely tested across page sizes, DPI, and typical parameter combinations. Other fonts are supported, but handwriting fonts vary significantly in their glyph metrics (character widths, ascenders/descenders, line spacing, and kerning). In addition, some “natural” effects intentionally apply small random shifts/rotations. Because you’re rendering into a fixed page area (margins + single page), certain font/effect combinations can occasionally:
  • look slightly different between requests (by design, when randomness is enabled)
  • fit tighter than expected for some text
  • touch margins or clip near edges in extreme cases
This is not something that can be made perfect for every font and every parameter combination, because the underlying font geometry and layout behavior differs. Recommendation: Before going to production, use /preview with representative text (and run it multiple times if you enable random effects). Once you find a stable combination for your use case, lock the font_id + settings in your config.

1. Filter by language

If your text includes non-Latin characters, filter fonts by language:
response = requests.get(
    "https://api.handtextai.com/api/v1/fonts",
    headers={"Authorization": f"Bearer {API_KEY}"},
)
fonts = response.json()["fonts"]

# Find fonts supporting Russian
russian_fonts = [f for f in fonts if "ru" in f["supported_languages"]]
print(f"Found {len(russian_fonts)} fonts with Russian support")

2. Test with preview

Use the free /preview endpoint to test fonts visually:
for font_id in [1, 2, 3, 4, 5]:
    response = requests.post(
        "https://api.handtextai.com/api/v1/preview",
        headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
        json={"text": "Sample text", "font_id": font_id, "font_size": 48, "page_size": "a5"},
    )
    # Save previews to compare styles
    save_preview(response.json(), f"font_{font_id}.png")

3. Lock your choice

Once you find a font you like, save the font_id in your config:
PREFERRED_FONT_ID = 3  # Lock this after testing

Language support

Common language codes

CodeLanguageNotes
enEnglishAll fonts
deGermanMost fonts
frFrenchMost fonts
esSpanishMost fonts
ruRussianCyrillic fonts only
ukUkrainianCyrillic fonts only
elGreekLimited fonts
jaJapaneseVery limited
hiHindiLimited fonts

Finding Cyrillic-capable fonts

cyrillic_fonts = [
    f["id"] for f in fonts
    if "ru" in f["supported_languages"] or "uk" in f["supported_languages"]
]

FAQ

Why are some characters missing?

The font doesn’t support those characters. Solutions:
  1. Check language support — Use /fonts to find a font that supports your language
  2. Stick to supported characters — Filter or validate input before sending
  3. Use a fallback font — Try font 1 (broad coverage) or font 10 (includes Japanese/Greek)

Why does my text look different than expected?

Fonts have different styles:
  • Some are more formal/cursive
  • Some are more casual/print-like
  • Line height and spacing vary
Use /preview to test before committing.

Which font should I use for…

Use caseSuggested fontsWhy
Professional letters1, 2, 3Clean, readable
Greeting cards4, 5, 6Friendly, casual
Multi-language (Cyrillic)1Broad coverage
Multi-language (Japanese)10CJK support

How do I match a specific handwriting style?

There’s no way to search by style. Use this approach:
  1. Generate previews for all 90 fonts (takes ~90 preview calls)
  2. Compare visually
  3. Narrow down to 3-5 candidates
  4. Test with real content
  5. Lock your final choice

Can I upload my own font?

Not currently. The API uses a curated set of licensed fonts.