Enlarge photos from code
Three ways in, one contract. The REST API runs Pro. The enlarge CLI and its local MCP server run Free on your machine with no key, and Pro with an API key.
Get an API key
Free needs no key in the CLI or MCP server. Pro needs an account with credits and an API key:
- Sign in with your email. There is no password; we send you a link.
- Buy a credit pack on your account page (see pricing).
- On the same page, create an API key under API keys. It starts with
enl_and is shown once, so store it somewhere safe.
Send it as Authorization: Bearer enl_…. You can have up to 10 keys and revoke any of them at any time. Keys spend the credits of the account that made them.
REST API
Base URL https://enlarge.photos/api/v1. Requests and responses are JSON, except the upload (multipart) and the download (the image). Enlarging is asynchronous: create a job, poll it, then download the result.
- Each job costs one credit, any size up to 100 MP. It is taken when the job is created and refunded automatically if the job fails.
- Results are kept for 24 hours, then deleted. We delete the upload when the job ends.
- Rate limits: 30 per minute new jobs and 60 per minute deletes per account, and 20 per minute failed key checks per IP address.
POST/api/v1/upscale
Creates a Pro job. Send multipart/form-data; the answer is 202 with the job.
| Field | Values | Default |
|---|---|---|
image | JPEG, PNG or WebP file, up to 50 MB | Required |
scale | 2, 4 | The largest that keeps the output within 100 MP |
mode | Deprecated: accepted and ignored (standard, high_fidelity, low_res) | None |
face_enhance | Deprecated: accepted and ignored (true, false) | None |
format | auto, jpeg, png, webp | auto (same as the input) |
curl https://enlarge.photos/api/v1/upscale \
-H "Authorization: Bearer enl_…" \
-F [email protected] \
-F scale=4
GET/api/v1/jobs/:id
Returns the job. status moves from queued to running to succeeded or failed, and a succeeded job becomes expired after 24 hours. Poll every 2 seconds. Only the account that created a job can see it.
curl https://enlarge.photos/api/v1/jobs/job_7Hk2mQ9xLp3vR8sT \
-H "Authorization: Bearer enl_…"
{
"job": {
"id": "job_7Hk2mQ9xLp3vR8sT",
"status": "succeeded",
"engine": "pro",
"mode": "standard",
"scale": 4,
"face_enhance": true,
"format": "auto",
"filename": "[email protected]",
"input": {
"width": 1200,
"height": 800
},
"output": {
"width": 4800,
"height": 3200
},
"credits": 1,
"output_bytes": 4182733,
"error": null,
"created_at": "2026-10-09T17:02:11.000Z",
"started_at": "2026-10-09T17:02:11.412Z",
"finished_at": "2026-10-09T17:02:24.903Z",
"expires_at": "2026-10-10T17:02:24.903Z",
"download_url": "https://enlarge.photos/api/v1/jobs/job_7Hk2mQ9xLp3vR8sT/download",
"thumbnail_url": "https://enlarge.photos/api/v1/jobs/job_7Hk2mQ9xLp3vR8sT/thumbnail"
}
}
GET/api/v1/jobs/:id/download
Returns the enlarged image. Before the job succeeds the answer is 409 not_ready; after 24 hours it is 410 expired.
curl https://enlarge.photos/api/v1/jobs/job_7Hk2mQ9xLp3vR8sT/download \
-H "Authorization: Bearer enl_…" \
-o [email protected]
GET/api/v1/jobs/:id/thumbnail
Returns a small preview of the result: a WebP image whose longest side is 384 pixels. A succeeded job links to it as thumbnail_url. Like the download, it answers 409 not_ready until the job succeeds and 410 expired once the result is deleted.
curl https://enlarge.photos/api/v1/jobs/job_7Hk2mQ9xLp3vR8sT/thumbnail \
-H "Authorization: Bearer enl_…" \
-o preview.webp
DELETE/api/v1/jobs/:id
Deletes the job and its files now, instead of after 24 hours. The credit is not refunded. While the job is queued or running the answer is 409 not_ready; wait for it to finish. A job that is already gone, or not yours, is 404 not_found.
curl -X DELETE https://enlarge.photos/api/v1/jobs/job_7Hk2mQ9xLp3vR8sT \
-H "Authorization: Bearer enl_…"
{
"deleted": true
}
GET/api/v1/jobs?limit=20
Your most recent jobs, newest first, as { "jobs": [...] }. limit is 1 to 100.
curl "https://enlarge.photos/api/v1/jobs?limit=20" \
-H "Authorization: Bearer enl_…"
GET/api/v1/me
The account the key belongs to and its credit balance.
curl https://enlarge.photos/api/v1/me \
-H "Authorization: Bearer enl_…"
{
"email": "[email protected]",
"credits": 59
}
A full round trip
Create, poll and download in one script (uses jq):
export ENLARGE_API_KEY=enl_…
JOB=$(curl -s https://enlarge.photos/api/v1/upscale \
-H "Authorization: Bearer $ENLARGE_API_KEY" \
-F [email protected] | jq -r .job.id)
# Poll every 2 seconds until the job leaves queued/running
while :; do
STATUS=$(curl -s https://enlarge.photos/api/v1/jobs/$JOB \
-H "Authorization: Bearer $ENLARGE_API_KEY" | jq -r .job.status)
[ "$STATUS" = queued ] || [ "$STATUS" = running ] || break
sleep 2
done
[ "$STATUS" = succeeded ] && curl -s https://enlarge.photos/api/v1/jobs/$JOB/download \
-H "Authorization: Bearer $ENLARGE_API_KEY" -o photo-enlarged.jpg
Errors
Every error has the same shape and an HTTP status that matches its code:
{
"error": {
"code": "insufficient_credits",
"message": "This needs 1 credit and you have 0. Buy credits at https://enlarge.photos/account#credits. Questions: [email protected]."
}
}
| Status | Code | Meaning |
|---|---|---|
401 | unauthorized | Sign in or send a valid API key (Authorization: Bearer enl_...). |
402 | insufficient_credits | Not enough credits. Buy credits at https://enlarge.photos/account#credits. Questions: [email protected]. |
403 | forbidden | You do not have access to this. |
404 | not_found | Not found. |
409 | not_ready | The job has not finished yet. |
410 | expired | The result has expired. Results are kept for 24 hours. |
422 | too_large | The image is too large. |
422 | invalid_input | The request is invalid. |
429 | rate_limited | Too many requests. Try again in a minute. |
502 | provider_error | The enlargement failed at our processor. Your credit was refunded. |
503 | unavailable | Pro is temporarily unavailable. Try again later. |
CLI
The enlarge command ships in the npm package enlarge-photos and needs Node 20 or later. Free runs the model on your machine and works offline; on a Mac it uses Core ML when it can.
npm i -g enlarge-photos
# Free: runs on your machine, offline, no key
enlarge photo.jpg
# Pro: our cloud AI, with your API key, asks before spending credits
export ENLARGE_API_KEY=enl_…
enlarge photo.jpg -e pro
Usage
enlarge <inputs...> [-s 2|4] [-e free|pro] [-f auto|jpeg|png|webp]
[-o <file|dir>] [--force] [--yes] [--json] [--verbose]
Inputs are files or folders (JPEG, PNG and WebP; folders are not searched recursively). Results are named <name>@<scale>x.<ext> and existing files are never overwritten without --force.
| Option | What it does |
|---|---|
-s 2|4 | Scale. Default: the largest that fits the engine's limit. |
-e free|pro | Engine. Default free. |
--mode | Deprecated. Still accepted, and ignored: Pro has no modes. |
--no-face-enhance | Deprecated. Still accepted, and ignored. |
-f | Output format: auto, jpeg, png, webp. Default auto, same as the input. |
-o <file|dir> | Where to write the result. |
--force | Overwrite existing files. |
--yes | Skip the Pro credit confirmation. Required when not running in a terminal. |
--json | Print one JSON object per result on stdout. |
--verbose | Show more detail, such as which accelerator ran. |
Commands
| Command | What it does |
|---|---|
enlarge login | Save your API key. Paste it at the hidden prompt or pipe it in; it is checked before saving. |
enlarge logout | Remove the saved key. |
enlarge whoami | Show the account and credit balance for the key. |
enlarge mcp | Start the MCP server on stdio (see below). |
enlarge --help | All options. |
Configuration and exit codes
- The key comes from
ENLARGE_API_KEY, else from~/.config/enlarge-photos/config.json(written byenlarge login, readable only by you;XDG_CONFIG_HOMEis respected). - Pro shows the credit total and asks before it spends anything. Progress goes to stderr, results to stdout.
- Exit codes:
0success,1error,2usage error,3not enough credits.
MCP server
enlarge mcp is a local MCP server on stdio. Your agent hands it a file path; the image is enlarged on your machine (Free) or in the cloud (Pro) and saved as a new file. Without a key, only Free is available.
npm i -g enlarge-photos
claude mcp add enlarge -e ENLARGE_API_KEY=enl_… -- enlarge mcp
# Free only, no key:
# claude mcp add enlarge -- enlarge mcp
Tools
| Tool | What it does |
|---|---|
upscale_image | Enlarges the image at path (absolute). Optional: scale, engine, format, output_path (mode and face_enhance are deprecated, accepted and ignored). Returns the output path, its size, the engine, credits used and credits left. |
estimate_cost | What a Pro enlargement of path would cost, computed locally. Optional scale. |
get_account | The account and credit balance for the configured key. |
Long jobs report progress to clients that ask for it. Try: Enlarge ~/Desktop/photo.jpg 4x or How much would a Pro enlargement of this photo cost?