Skip to main content

Python SDK for the Lipi.ai Font Intelligence API

Project description

lipi

Python SDK for the Lipi.ai Font Intelligence API.

Identify fonts from images and scan websites for font licensing compliance.

Install

pip install lipi

For async support:

pip install lipi[async]

Quick Start

import lipi

client = lipi.Client(api_key="lpi_...")

# Identify fonts in an image
result = client.font_match("screenshot.png")
for text in result.texts:
    print(f'"{text.text}" → {text.best_match}')
    print(f"  Free alternatives: {', '.join(text.free_alternatives)}")

# Scan a URL for font compliance
scan = client.url_scan("https://stripe.com")
print(f"Risk: {scan.compliance_summary.overall_risk}")
for font in scan.fonts_detected:
    print(f"  {font.family}")

Authentication

API key is resolved in this order:

  1. Client(api_key="lpi_...")
  2. LIPI_API_KEY environment variable
  3. ~/.lipi/config.toml (set via CLI)
# Save your key via CLI
lipi auth set-key lpi_your_key_here

API Reference

Client(api_key=None, base_url="https://api.lipi.ai", timeout=30)

Font Identification

# High-level: submit + poll until done
result = client.font_match("image.png")

# Low-level: manual polling
job = client.submit_font_match("image.png")
status = client.get_font_match(job.job_id)

Input formats: file path (str/Path), bytes, file-like object, or base64 data URL.

URL Scanning

# High-level: submit + poll until done
scan = client.url_scan("https://example.com")

# Low-level: manual polling
job = client.submit_url_scan("https://example.com")
status = client.get_url_scan(job.job_id)

Credits & Usage

balance = client.get_credits()
print(f"Free: {balance.free_credits_remaining}")
print(f"Paid: {balance.paid_credits_remaining}")

history = client.get_usage(limit=20, from_date="2026-04-01")
for entry in history.usage:
    print(f"{entry.timestamp} {entry.endpoint} {entry.credits_charged} credits")

Batch Processing

Process an entire folder of images with crash recovery:

from lipi import Client
from lipi.batch import batch_font_match

client = Client()

# Process all images → CSV (resumes automatically if interrupted)
stats = batch_font_match(
    client,
    input_dir="./screenshots",
    output="results.csv",
)
print(f"{stats.succeeded}/{stats.total} succeeded")

Crash recovery works by reading the output CSV on startup and skipping already-processed files. Results are flushed after each image, so at most one image of work is lost on crash.

# Retry only failed images
stats = batch_font_match(client, "./screenshots", "results.csv", retry_failed=True)

# Force re-process everything
stats = batch_font_match(client, "./screenshots", "results.csv", resume=False)

CSV output (one row per text region detected):

filename,status,text,best_match,commercial_alternatives,free_alternatives,reasoning,job_id,processed_at,error
logo.png,succeeded,ACME,Futura Bold,"Avant Garde, Kabel","Jost, Nunito Sans","Geometric sans-serif...",abc123,2026-04-18T10:00:00Z,

Batch URL scanning:

from lipi.batch import batch_url_scan

stats = batch_url_scan(client, urls="urls.txt", output="scan_results.csv")

Async Client

import asyncio
from lipi import AsyncClient

async def main():
    async with AsyncClient() as client:
        result = await client.font_match("screenshot.png")
        print(result.texts[0].best_match)

asyncio.run(main())

Exceptions

from lipi import (
    LipiError,                # Base
    AuthenticationError,      # 401/403 — bad or revoked API key
    InsufficientCreditsError, # 402 — no credits remaining
    RateLimitError,           # 429 — too many requests (.retry_after seconds)
    ImageError,               # 413/422 — invalid or too-large image
    JobFailedError,           # Job processing failed (.job_id)
    ServerError,              # 5xx — server-side error
    TimeoutError,             # Polling timed out (.job_id)
)

CLI

# Font identification
lipi font-match image.png
lipi font-match image.png --json-output
lipi font-match image.png -o results.json

# URL scanning
lipi url-scan https://stripe.com
lipi url-scan https://stripe.com --json-output

# Batch processing
lipi batch ./screenshots --output results.csv
lipi batch ./screenshots --output results.csv --retry-failed
lipi batch ./screenshots --output results.csv --no-resume

# Batch URL scanning
lipi batch-urls urls.txt --output scan_results.csv

# Account
lipi credits
lipi usage --limit 20 --from 2026-04-01

# Auth
lipi auth set-key lpi_your_key
lipi auth show

CLI Output Example

Analyzed screenshot.png in 12.3s

Found 2 text region(s):

  "NIZO"
  Best match:  Eurostile Extended Bold Italic
  Commercial:  Microgramma D Extended Bold Italic, ITC Machine Bold Oblique
  Free:        Michroma, Orbitron Bold

  "Premium Quality"
  Best match:  Garamond Premier Pro
  Commercial:  Adobe Garamond, Sabon
  Free:        EB Garamond, Cormorant Garamond

Credits remaining: 8 (6 free + 2 paid)

Batch CLI Output

Credits available: 42 (6 free + 36 paid)
Input: ./screenshots
Output: results.csv

[1/35] analyzing logo_v2.png... done
[2/35] analyzing banner.png... done
[3/35] analyzing social.png... failed

Batch complete in 423.1s: 33 succeeded, 2 failed, 12 skipped
Results saved to results.csv
Credits remaining: 7 (0 free + 7 paid)

Response Models

All API responses are typed Pydantic models:

  • FontMatchResult — font identification results
    • .results: list[TextResult] — per-text-region matches
    • .texts — alias for .results
  • TextResult — single text region
    • .best_match — most likely commercial font
    • .commercial_alternatives — close commercial alternatives
    • .free_alternatives — closest free alternatives
    • .reasoning — analysis reasoning
  • UrlScanResult — URL scan results
    • .fonts_detected: list[FontDetected]
    • .license_results: list[LicenseResult]
    • .compliance_summary: ComplianceSummary
  • CreditBalance — credit balance
    • .total_credits — free + paid
  • UsageHistory — paginated usage logs
  • BatchStats — batch processing summary

Pricing

  • Free tier: 10 credits/month
  • Subscription: $75/month for 100 credits
  • Top-up: $60 for 100 additional credits (subscribers only)
  • Each font_match or url_scan call costs 1 credit
  • Failed jobs are automatically refunded

Get your API key at lipi.ai/dashboard/api-keys.

Development

git clone https://github.com/lipi-ai/lipi-python.git
cd lipi-python
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lipi-0.1.2.tar.gz (615.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lipi-0.1.2-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

Details for the file lipi-0.1.2.tar.gz.

File metadata

  • Download URL: lipi-0.1.2.tar.gz
  • Upload date:
  • Size: 615.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for lipi-0.1.2.tar.gz
Algorithm Hash digest
SHA256 2c5f0c6e4a05ea398cc006c63fa692ee0081fb795f01ce84b41bf5ea1f8dc484
MD5 46b953e00c0997b0c5bd6acf5bc397bf
BLAKE2b-256 eb48f8ff629d4c0fe11562e4d30331d60f57a8055be8ebb2aa6aabdd47d09989

See more details on using hashes here.

File details

Details for the file lipi-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: lipi-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 22.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for lipi-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 bbd79ce7ae977a31af3316550b9ee9f39f6a7b6056c2f4fd5b9c8838e245fae4
MD5 ebefc1b2149baf8990ba0ba0af0041ba
BLAKE2b-256 427de43fa48666fbe23ac9be53ba9f2c9c06bebe48ee9340edeeffc6de603add

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page