Python SDK & CLI
The official Python SDK wraps the Lipi.ai API into a clean library and command-line tool. Install it with pip, authenticate once, and start identifying fonts or scanning URLs in seconds.
What You Get
- One-line install —
pip install lipi. Works on Python 3.9+, Windows, macOS, and Linux. - Python client — type-safe Pydantic models, built-in polling, automatic error handling.
- CLI tool — run
lipi font-match image.pngdirectly from your terminal. - Batch processing — process an entire folder of images or a list of URLs, output to CSV, with crash-and-resume built in.
- Async support —
pip install lipi[async]for httpx-based async client.
Prerequisites
You need a Lipi.ai API key. If you don't have one yet, follow the Developer API Setup Guide to apply for access and generate your key.
Getting Started
Install the SDK
pip install lipiThis installs the lipi library and the lipi CLI command. For async support, install with the async extra:
pip install lipi[async]Save your API key
Run this once to store your key locally:
lipi auth set-key lpi_YOUR_KEY_HEREThis saves the key to ~/.lipi/config.toml. You can also set it as an environment variable:
export LIPI_API_KEY=lpi_YOUR_KEY_HEREThe SDK checks for the key in this order: explicit parameter → LIPI_API_KEY env var → config file.
Identify fonts from the terminal
lipi font-match screenshot.pngOutput:
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)Add --json-output for machine-readable JSON, or -o results.json to save to a file.
Scan a URL for font compliance
lipi url-scan https://stripe.comOutput:
Scanned https://stripe.com in 18.5s
Page: Stripe | Financial Infrastructure
Overall: LOW (score: 100/100)
Fonts found: 3
Inter [400, 500, 700] low
License: SIL Open Font License
Commercial: Allowed
Stripe Custom [400, 600] medium
License: Custom / Proprietary
system-ui [400] low
License: System Font
Credits remaining: 7 (5 free + 2 paid)Use it in Python code
The SDK abstracts away the async job pattern — submit and poll are handled automatically:
import lipi
client = lipi.Client(api_key="lpi_YOUR_KEY_HERE")
# Identify fonts in an image
result = client.font_match("screenshot.png")
for region in result.results:
print(f"Text: {region.text}")
print(f"Best match: {region.best_match}")
print(f"Free alternatives: {region.free_alternatives}")
print()
# Scan a URL for font compliance
scan = client.url_scan("https://example.com")
print(f"Risk: {scan.compliance_summary.overall_risk}")
for font in scan.fonts_detected:
print(f" {font.family}: {font.weights}")
# Check your credit balance
credits = client.get_credits()
print(f"Credits: {credits.total_credits}")The font_match() method accepts file paths, Path objects, or raw bytes.
Batch Processing
Process an entire folder of images or a list of URLs at once. Results are saved to a CSV file.
Batch font identification
# Process all images in a folder
lipi batch ./screenshots --output results.csv
# Force re-process everything (ignore previous results)
lipi batch ./screenshots --output results.csv --no-resume
# Only retry previously failed images
lipi batch ./screenshots --output results.csv --retry-failedBatch URL scanning
Create a text file with one URL per line, then:
lipi batch-urls urls.txt --output scan_results.csvFrom Python code
from lipi import Client
from lipi.batch import batch_font_match, batch_url_scan
client = Client()
# Batch font match
stats = batch_font_match(
client,
input_dir="./screenshots",
output="results.csv",
)
print(f"{stats.succeeded}/{stats.total} succeeded")
# Batch URL scan
stats = batch_url_scan(
client,
urls="urls.txt",
output="scan_results.csv",
)Crash Recovery
Batch processing is designed for reliability. If the process crashes or you press Ctrl+C, just re-run the same command — it picks up where it left off automatically.
- Append-mode CSV — results are appended one at a time and flushed to disk after each image. At most one image of work is lost on crash.
- Automatic resume — on restart, already-processed filenames are read from the CSV and skipped.
- Rate limit handling — if the API returns 429 (too many requests), the SDK automatically waits and retries.
- Credit awareness — batch stops early if you run out of credits, preserving all work done so far.
CSV Output Format
The font-match CSV has one row per text region detected (one image may produce multiple rows):
filename,status,text,best_match,commercial_alternatives,free_alternatives,job_id,processed_at,error
logo.png,succeeded,NIZO,Eurostile Extended Bold,"Microgramma, ITC Machine","Michroma, Orbitron",f760cd...,2026-04-18T10:30:00Z,
logo.png,succeeded,Premium,Garamond Premier Pro,"Adobe Garamond, Sabon","EB Garamond, Cormorant",f760cd...,2026-04-18T10:30:00Z,
broken.png,failed,,,,,,a1b2c3...,2026-04-18T10:30:12Z,Processing failedThe URL scan CSV contains font and license data per URL:
url,status,page_title,font_family,weights,risk_level,license_type,overall_risk,overall_score,job_id,processed_at,error
https://stripe.com,succeeded,Stripe,Inter,"400, 500, 700",low,SIL OFL,low,100,a1b2c3...,2026-04-18T10:31:00Z,All CLI Commands
lipi auth set-key <key>Save your API key locallylipi auth showShow the currently configured API keylipi font-match <image>Identify fonts in an imagelipi url-scan <url>Scan a URL for font compliancelipi batch <folder>Batch-process a folder of imageslipi batch-urls <file>Batch-scan URLs from a text filelipi creditsCheck your credit balancelipi usageView API usage historyAll commands support --help for detailed options.
Error Handling
The SDK raises typed exceptions so you can handle errors precisely:
from lipi.exceptions import (
AuthenticationError, # 401 — invalid or missing key
InsufficientCreditsError, # 402 — no credits left
RateLimitError, # 429 — too many requests
JobFailedError, # Job processing failed
ImageError, # Invalid image format/size
ServerError, # 5xx server errors
)
try:
result = client.font_match("image.png")
except RateLimitError as e:
print(f"Rate limited. Retry in {e.retry_after}s")
except InsufficientCreditsError:
print("Out of credits!")
except AuthenticationError:
print("Check your API key")