No API key. No account. No sign-up. Post a photo and a country code, get a correctly cropped passport photo back, plus the head height we measured so you can check it yourself.
Last updated: 1 September 2026
This is the same engine the PassportNinja website runs on. Free to call, and there is nothing to register for.
$ curl -s -F "[email protected]" -F "country=nl" \
https://passportninja.com/api/photo
{
"job_id": "041379c97a80",
"template": "Netherlands — passport/ID (35×45 mm)",
"photo": "/api/result/041379c97a80/photo.png",
"photo_jpg": "/api/result/041379c97a80/photo.jpg",
"sheet": "/api/result/041379c97a80/sheet.jpg",
"size_mm": [35.0, 45.0],
"head_mm": 34.2,
"head_range_mm": [32.0, 36.0],
"bewaar_min": 45,
"warnings": []
}
$ curl -s -o passport.png \
https://passportninja.com/api/result/041379c97a80/photo.png
Most passport photo tools hand you a crop and leave you hoping. This one tells you what it did:
head_mm | The head height it actually produced, in millimetres. |
|---|---|
head_range_mm | The range that country requires. |
size_mm / size_px | The photo size in millimetres and in pixels. |
warnings | Anything worth telling the person, such as a photo framed too tightly to crop cleanly. |
If head_mm falls inside head_range_mm, the crop is within spec. That is a check you can run in your own code instead of trusting us.
Every job also produces printable sheets, listed under sheets in the response. Right now that is 10×15 cm with 8 photos, US Letter with 25, and A4 with 30. Fetch whichever url you want, the same way as the single photo.
13 formats at the time of writing. Do not hard-code them, ask:
$ curl -s https://passportninja.com/api/templates
[{"key":"us","label":"United States — passport & visa (2×2 in)","size_mm":[50.8,50.8]},
{"key":"nl","label":"Netherlands — passport/ID (35×45 mm)","size_mm":[35.0,45.0]}, ...]
Pass the key you want as the country field. Leave it out and you get the general Schengen size.
| Name | Required | What it does |
|---|---|---|
file | yes | The photo. A sharp, front-facing shot with the whole head visible. |
country | no | A key from /api/templates. Defaults to the general Schengen format. |
| Maximum file size | 99 MB |
|---|---|
| Running at once | 3 per IP address |
| Requests per day | No cap |
| Result stays available | 45 minutes, or 24 hours with a €5 pass |
| Status | Meaning |
|---|---|
422 | No face found, or the file field is missing. The message says which. |
413 | The photo is over 99 MB. |
429 | Three jobs already running from this address. |
Build on it, including in something you charge for. If your project lists what it uses, a link back to passportninja.com is what keeps this free. Planning real volume? Say hello on the contact page first.
No. No key, no account, no sign-up.
Compare head_mm against head_range_mm in the response. Both are returned on every job.
Almost always because no face was detected. Use a front-facing photo with the whole head in frame and nothing cropping the top of the head.
45 minutes, then the files are deleted. With a €5 ShinobiTools pass the same job stays available for 24 hours.
13 formats at the moment, including the United States, the United Kingdom, the Netherlands, India, China and the general Schengen size. Call GET /api/templates for the current list rather than hard-coding it.
The response tells you. It returns head_mm, the head height it measured, and head_range_mm, the range the country requires. If the first falls inside the second, the crop is within spec.
You get HTTP 422 with a message saying no face was found. Use a sharp, front-facing photo with the whole head visible.
45 minutes without a pass, then the job id stops working and the files are gone. With a EUR 5 ShinobiTools pass the result stays available for 24 hours.
Terms are on the terms page, and what happens to your photo is on the privacy page.