IDPhotoSnap๐ŸŽจ BG

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

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"
end

Document 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