Passport Photo API
Turn any photo into a compliant passport or visa photo. Face detection, automatic framing to each government's head-size and eye-line rules, and a correctly sized file at 300 DPI.
Quick start
No sign-up, no API key. Send a front-facing photo and a document type, get back a correctly framed photo.
curl -X POST https://2x2passportphoto.com/api/v1/photos \
-H "Content-Type: application/json" \
-d '{
"image": "<base64-encoded photo>",
"document": "us-passport"
}'Base URL https://2x2passportphoto.com · OpenAPI spec /api/v1/openapi.json
What is free, what costs money
Free: face detection, cropping, resizing and the finished photo with a watermark across it. Everything the API returns is free.
$9.99 one-time: the same photo without the watermark, print-ready. The response includes a checkout.url you can hand to the user; they pay there and download it. There is no subscription and no per-seat fee.
You are never charged for calling the API. The payment is between the end user and us, at the point they want the clean file.
Rate limits
POST /api/v1/photos— 10 requests per minute per IP.- Read endpoints — 60 requests per minute per IP.
Exceeding a limit returns 429 with a Retry-After header. Need more? Get in touch.
Endpoints
Creates a compliant photo. The source should be front-facing with the whole head visible and even lighting.
{
"image": "<base64, or a data:image/jpeg;base64,... URL>",
"document": "us-passport",
"email": "optional@example.com"
}Response
{
"id": "api_mh8x2k_9fjs02la",
"document": {
"id": "us-passport",
"name": "US Passport",
"output": { "width": 600, "height": 600, "dpi": 300,
"inches": "2×2", "mm": "51×51" }
},
"photo": {
"watermarked": true,
"width": 600, "height": 600, "dpi": 300,
"data": "data:image/jpeg;base64,..."
},
"checkout": {
"url": "https://2x2passportphoto.com/result/api_mh8x2k_9fjs02la",
"price": { "amount": 9.99, "currency": "USD" },
"description": "One-time payment for the watermark-free file."
}
}Max image size 10MB. Images larger than ~1500px on the long edge are downscaled before detection, so sending a 12MP phone photo only costs you upload time.
Whether that photo has been purchased yet. Returns paid, a previewUrl (watermarked, always available) and a downloadUrl once it is paid for.
All 41 supported document types with the exact pixel dimensions each one returns.
One document in full: output size, the framing ratios we target, and the issuing authority's rules on background, glasses, expression and clothing — plus the reasons photos of that type get rejected.
Errors
Every error returns the same shape. Branch on code; hint says what to do about it.
{
"error": {
"code": "no_face_detected",
"message": "No face detected. Use a front-facing photo where the whole head is visible.",
"hint": "Use a straight-on photo with the whole head visible and even lighting."
}
}| Code | HTTP | Meaning |
|---|---|---|
| invalid_request | 400 | A required field is missing or malformed |
| unsupported_document | 400 | Unknown document id — check /api/v1/documents |
| image_too_large | 413 | Image exceeds 10MB |
| invalid_image | 422 | The bytes could not be decoded as an image |
| no_face_detected | 422 | No face found in the photo |
| rate_limited | 429 | Too many requests — see Retry-After |
| not_found | 404 | Unknown photo or document id |
| service_unavailable | 503 | Face detection temporarily down |
Supported documents (41)
Pass any id below as the document field. Aliases resolve to the same spec.
| id | Name | Output | Size |
|---|---|---|---|
| australia-passport | Australia Passport | 413×531 | 35×45 mm |
| australia-visa | Australia Visa | 413×531 | 35×45 mm |
| bangladesh-passport | Bangladesh Passport | 413×531 | 35×45 mm |
| brazil-visa | Brazil Visa | 590×826 | 50×70 mm |
| canada-passport | Canada Passport | 590×826 | 50×70 mm |
| canada-visa | Canada Visa | 590×826 | 50×70 mm |
| china-passport | China Passport | 390×567 | 33×48 mm |
| china-visa | China Visa | 390×567 | 33×48 mm |
| generic-35x45 | Standard 35×45mm | 413×531 | 35×45 mm |
| hongkong-passport | Hong Kong Passport | 472×591 | 40×50 mm |
| hongkong-visa | Hong Kong Visa | 472×591 | 40×50 mm |
| india-passport | India Passport | 600×600 | 51×51 mm |
| india-visa | India Visa | 413×531 | 35×45 mm |
| indonesia-visa | Indonesia Visa | 413×531 | 35×45 mm |
| japan-passport | Japan Passport | 413×531 | 35×45 mm |
| japan-visa | Japan Visa | 413×531 | 35×45 mm |
| malaysia-passport | Malaysia Passport | 413×591 | 35×50 mm |
| malaysia-visa | Malaysia Visa | 413×591 | 35×50 mm |
| mexico-visa | Mexico Visa | 413×531 | 35×45 mm |
| nz-passport | New Zealand Passport | 413×531 | 35×45 mm |
| nz-visa | New Zealand Visa | 413×531 | 35×45 mm |
| pakistan-nadra | Pakistan NADRA | 413×531 | 35×45 mm |
| philippines-passport | Philippines Passport | 413×531 | 35×45 mm |
| russia-visa | Russia Visa | 413×531 | 35×45 mm |
| saudi-visa | Saudi Arabia Visa | 413×531 | 35×45 mm |
| schengen-visa | Schengen Visa | 413×531 | 35×45 mm |
| singapore-passport | Singapore Passport | 413×531 | 35×45 mm |
| singapore-visa | Singapore Visa | 413×531 | 35×45 mm |
| south-korea-visa | South Korea Visa | 413×531 | 35×45 mm |
| taiwan-passport | Taiwan Passport | 413×531 | 35×45 mm |
| taiwan-visa | Taiwan Visa | 413×531 | 35×45 mm |
| thailand-visa | Thailand Visa | 413×531 | 35×45 mm |
| turkey-visa | Turkey Visa | 591×709 | 50×60 mm |
| uae-passport | UAE Passport | 472×709 | 40×60 mm |
| uae-visa | UAE Visa | 413×531 | 35×45 mm |
| uk-passport | UK Passport | 413×531 | 35×45 mm |
| uk-visa | UK Visa | 413×531 | 35×45 mm |
| us-dv-lottery | US DV Lottery | 600×600 | 51×51 mm |
| us-passport | US Passport | 600×600 | 51×51 mm |
| us-visa | US Visa | 600×600 | 51×51 mm |
| vietnam-visa | Vietnam Visa | 472×709 | 40×60 mm |
Photos and privacy
A photo you send is processed and stored against the order id returned to you, so the user can come back and buy the clean file. It is not used for training and is not shared. Tell your users their photo is being sent to us to be processed.
Questions
Higher limits, a different document type, or something not working? Get in touch.