Why your passport photo keeps getting rejected (it's the file, not the picture)
Source: Dev.to
If you’ve ever uploaded a passport photo to a government portal and gotten a vague “photo rejected” error, the problem usually isn’t the picture itself—it’s the file.
I run IDPhotoSnap, a free browser‑based passport‑photo tool. The single most common support question is a variation of “my photo looks fine, why does the portal say it’s wrong?”
The answer almost always lives in the file’s metadata, not the visible image.
The 8 file‑level rejection reasons
1. File size out of range
Most embassy portals enforce strict caps:
- US State Department DS‑160: 240 KB max
- UK passport portal: 50 KB – 10 MB
- Schengen visa portals: 240 KB – 6 MB (varies by country)
- India passport Seva: 20 KB – 300 KB
A modern phone shoots 4–8 MB by default, so the portal often rejects the upload before any human ever sees the picture.
2. Wrong DPI
DPI is stored in metadata; it doesn’t change the pixel data. Phone cameras tag photos at 72 DPI, while embassy print pipelines require 300 DPI.
// In a JPEG, DPI lives in the JFIF header (bytes 13‑18) or EXIF tag 0x011A.
// Changing it does NOT recompress or resize – just rewrites those bytes.
You can verify the DPI with ImageMagick:
identify -format "%x x %y\n" photo.jpg # → 72x72 (needs 300x300)
The pixel content is identical; the metadata tag is what trips the validator.
3. Wrong dimensions
Every country uses different size requirements:
| Country | Size |
|---|---|
| US | 600 × 600 px (2 × 2 in) |
| Schengen | 35 × 45 mm |
| UK | 35 × 45 mm at 600 × 750 px minimum |
| India | 51 × 51 mm at 600 × 600 px |
| Japan | 35 × 45 mm at 413 × 531 px |
A photo that passes for one country will fail for another—there’s no universal size.
4. Wrong format (HEIC, WebP, PNG)
iPhones save HEIC by default; Android sometimes saves WebP. Most government portals accept only JPG, and about half also reject PNG.
The HEIC → JPG conversion can be done client‑side with libheif compiled to WASM:
import { decode } from 'libheif-js'
async function heicToJpeg(file) {
const buf = await file.arrayBuffer()
const decoder = new Decoder()
const data = decoder.decode(new Uint8Array(buf))
// …draw onto canvas, export as JPEG with quality 0.92
}
5. Background isn’t pure white
Background validators look for RGB(255,255,255) ± a small delta. Common failures:
- Off‑white walls (255, 250, 245)
- Window‑light gradients across the wall
- Soft shadow behind the head
For true compliance, replace the background entirely. In‑browser ML segmentation models like MODNet (~25 MB ONNX) run via onnxruntime-web.
6. Compression artifacts
A quality‑60 % JPEG shows visible block artifacts. Validators sometimes flag low SSIM. Re‑compress at 90‑95 % quality; if the file is still too large, reduce pixel dimensions—but never drop below the size threshold.
7. Color profile mismatch
Photos taken on iPhones may be in Display‑P3, while validators expect sRGB. Convert before export:
ctx.imageSmoothingEnabled = true
ctx.drawImage(img, 0, 0)
const data = ctx.getImageData(0, 0, w, h)
// Canvas defaults to sRGB – drawing converts the profile
8. Embedded thumbnail mismatch
Some portals compare the EXIF thumbnail to the main image. If they differ (e.g., you cropped the main image but the thumbnail remains the original), the file is flagged as edited. Strip EXIF entirely:
// Re‑encoding via canvas removes all EXIF/XMP/IPTC metadata
canvas.toBlob(blob => {
// upload blob …
}, 'image/jpeg', 0.95)
Why a browser‑only tool makes sense here
All the operations above are pure pixel manipulation and can be performed locally in the browser—no server compute, no cloud AI. Even background replacement runs locally with onnxruntime-web in ~2‑5 seconds on a mid‑range laptop.
Uploading a photo of your face to a third‑party service to do work that runs fine in WebAssembly is bad architecture and worse for privacy.
If you want to see this approach in action, IDPhotoSnap handles all eight issues for 85+ countries with zero uploads. Its Photo Rejected hub diagnoses a rejected photo and fixes the specific problem, entirely client‑side.
Lesson
When a government portal rejects “a fine‑looking photo,” 90 % of the time it’s reading the file’s metadata, not the picture. Engineering for this is mostly about being deliberate with what you write into the JPEG header—DPI tag, dimensions, color profile, embedded thumbnails—rather than the pixels themselves.
FAQ
Q: Why do passport portals not give specific error messages?
A: They run a chain of validators (size → format → DPI → dimensions → background) and abort on the first failure. Some only surface the last failure code; many give no useful feedback at all.
Q: Will printing the photo fix DPI?
A: Yes for in‑person submission, but no for online portals—they read the file metadata, not the print.
Q: Can I just convert HEIC to JPG and call it done?
A: Often yes for size and format checks, but the converter usually resets the DPI tag to 72 DPI and leaves the phone‑default dimensions unchanged, so you often also need a resize and a DPI rewrite.
Q: Is server‑side processing ever needed for this?
A: Not for 99 % of cases. Background removal is the only borderline case (large model file). Everything else fits comfortably in Canvas plus a few KB of JavaScript.