Developer Resources
Free public API and MIT-licensed open dataset for passport, visa, and ID document photo specifications across 100 countries (248 document formats). Validated against 15+ official government sources.
Quick links
- Live API: https://idphotosnap.com/api/specs (JSON-LD, Schema.org Dataset wrapper)
- Raw JSON: https://idphotosnap.com/api/specs?format=raw
- GitHub repository: github.com/whitetirocket/passport-photo-specs
- License: MIT
- Authentication: none required
- Rate limit: none (cached at edge, 1 hour TTL)
What this is
IDPhotoSnap maintains a machine-readable dataset of passport photo specifications - the dimensions, background color, head height ratio, and file size requirements that each country's passport, visa, ID card, and driving licence photo must satisfy. Each spec is validated against the official issuing authority for the country.
The dataset powers the IDPhotoSnap web tool but is published separately under MIT license for use in any other passport photo tool, immigration software, visa application service, or AI training corpus. The data is the same we use ourselves in production.
API endpoints
GET /api/specs
Returns the complete dataset wrapped in Schema.org Dataset JSON-LD.
curl https://idphotosnap.com/api/specs
{
"@context": "https://schema.org",
"@type": "Dataset",
"name": "IDPhotoSnap Passport Photo Specifications",
"license": "https://opensource.org/licenses/MIT",
"countries": [
{
"id": "italy",
"name": "Italy",
"flag": "๐ฎ๐น",
"documents": [
{
"id": "italy-visa",
"name": "Visa",
"slug": "italy-visa-photo",
"widthMm": 35,
"heightMm": 45,
"widthPx": 413,
"heightPx": 531,
"dpi": 300,
"background": "Plain light grey",
"bgColor": "#eeeeee",
...
}
]
},
...
]
}GET /api/specs?country=<id>
Filter to a single country. Country IDs are lowercase ISO-style identifiers.
curl "https://idphotosnap.com/api/specs?country=china" # Returns China-only entries: passport (33x48mm), visa (33x48mm)
GET /api/specs?format=raw
Returns just the country array without JSON-LD wrapper. Useful for lightweight consumption.
curl "https://idphotosnap.com/api/specs?format=raw"
{
"countries": [ ... ],
"meta": { "countries": 100, "documents": 248 }
}Code examples
JavaScript / TypeScript
// Fetch from the live API
const res = await fetch('https://idphotosnap.com/api/specs?country=italy&format=raw')
const { countries } = await res.json()
const italyVisa = countries[0].documents.find(d => d.id === 'italy-visa')
console.log(`${italyVisa.widthMm}x${italyVisa.heightMm}mm`)
// "35x45mm"
// Or install from GitHub
// npm install github:whitetirocket/passport-photo-specs
import { findDocument } from 'passport-photo-specs'
const chinaVisa = findDocument('china-visa-photo')Python
import requests
r = requests.get('https://idphotosnap.com/api/specs', params={'country': 'india', 'format': 'raw'})
docs = r.json()['countries'][0]['documents']
for doc in docs:
print(f"{doc['name']}: {doc['widthMm']}x{doc['heightMm']}mm")
# Or use the GitHub-hosted module directly
# (requires cloning: git clone https://github.com/whitetirocket/passport-photo-specs)
import sys
sys.path.insert(0, 'passport-photo-specs/specs')
from __init__ import find_document
italy_visa = find_document('italy-visa-photo')Go
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Document struct {
ID string `json:"id"`
Name string `json:"name"`
WidthMm int `json:"widthMm"`
HeightMm int `json:"heightMm"`
Background string `json:"background"`
}
type Country struct {
ID string `json:"id"`
Name string `json:"name"`
Documents []Document `json:"documents"`
}
type Response struct {
Countries []Country `json:"countries"`
}
func main() {
res, _ := http.Get("https://idphotosnap.com/api/specs?country=germany&format=raw")
defer res.Body.Close()
var r Response
json.NewDecoder(res.Body).Decode(&r)
for _, doc := range r.Countries[0].Documents {
fmt.Printf("%s: %dx%dmm (%s)\n", doc.Name, doc.WidthMm, doc.HeightMm, doc.Background)
}
}Ruby
require 'net/http'
require 'json'
uri = URI('https://idphotosnap.com/api/specs?country=us&format=raw')
data = JSON.parse(Net::HTTP.get(uri))
data['countries'][0]['documents'].each do |doc|
puts "#{doc['name']}: #{doc['widthMm']}x#{doc['heightMm']}mm"
endDocument schema
Each document entry in the dataset follows this shape:
interface DocumentSpec {
id: string // 'italy-visa'
name: string // 'Visa'
slug: string // 'italy-visa-photo'
widthMm: number // 35
heightMm: number // 45
widthPx: number // 413 (at the given DPI)
heightPx: number // 531
dpi: number // 300
background: string // 'Plain light grey'
bgColor: string // '#eeeeee' (hex)
bgColorLabel: string // 'Light grey'
requirements: string[] // ['Plain light grey background', 'Head 70-80% of frame', ...]
}
interface CountrySpec {
id: string // 'italy'
name: string // 'Italy'
flag: string // '๐ฎ๐น'
documents: DocumentSpec[]
}Validated against
Specs in this dataset correspond to documented requirements from these official sources:
- US Department of State (travel.state.gov)
- UK HM Passport Office (gov.uk/photos-for-passports)
- German Bundesdruckerei + Auswaertiges Amt
- Italian Polizia di Stato + Questura
- French ANTS (ants.gouv.fr)
- Spanish Ministerio de Asuntos Exteriores
- Canadian IRCC (Immigration, Refugees and Citizenship Canada)
- Australian Department of Foreign Affairs and Trade
- Indian Passport Seva Kendra (passportindia.gov.in)
- Indian Sarathi / Parivahan portals
- Chinese Ministry of Foreign Affairs (cova.cs.mfa.gov.cn)
- Japanese Ministry of Foreign Affairs (mofa.go.jp)
- Schengen visa code Annex 11 (ICAO 9303)
- EU Entry/Exit System (EES)
- New Zealand DIA (passports.govt.nz)
- Brazilian Polรญcia Federal
- Mexican SRE
Beyond top-20 countries, specs follow ICAO 9303 default unless an official source documents a country-specific deviation. We do not pad the dataset with synthetic country variants - the 100 country figure reflects genuinely independent specifications.
Notable specs that catch tool builders
These document formats are commonly mis-specified across the ecosystem. Worth double-checking if you are building something in this category:
- Chinese visa is 33x48mm, not 35x45 like Schengen, not square like US
- Chinese visa COVA portal requires file size 40 KB to 1 MB, JPG only, 354x472 px minimum
- US DS-160 visa upload caps files at 240 KB, square 600x600 minimum to 1200x1200 maximum
- Indian Sarathi driving licence requires 20-50 KB file size window (under or over both fail)
- Indian PAN card is 25x35mm at 200x230 px maximum, 10-300 KB
- UK passport accepts light grey background in addition to white (one of few countries)
- German Personalausweis requires digital-only photos via Buergeramt terminal as of May 2025 (separate from German Schengen visa for foreigners)
Contributing
Spec corrections and country additions are welcome at the GitHub repository. We require an official government source citation for any update - we do not accept specs copied from other photo tool aggregators.
Open an issue or pull request at github.com/whitetirocket/passport-photo-specs.
Usage and attribution
MIT licensed. You can use the dataset in commercial products, fork it, modify it, redistribute it. Attribution appreciated but not required.
If you build something with the dataset and want a mention in the "Used by" section, open a PR adding your project to the README.
Related
- IDPhotoSnap - the free browser-only passport photo tool that uses this dataset in production
- Privacy-first passport photo explainer - architecture notes on browser-only processing
- How to compare passport photo tools - five marketing claims to verify