Introducing veriwell-capture
Today we’re publishing veriwell-capture, the browser toolkit behind the camera steps in Veriwell, our identity verification service. It handles the part of an ID check that people actually see: holding a passport up to a camera, getting a sharp photo without glare, and following a few head movements for a selfie. It’s released under the Apache License 2.0, and the code is at github.com/vestra-corp/veriwell-capture.
Why we’re publishing it
Most of the friction in identity checks happens before any verification starts. The photo is blurred, a light bounces off the laminate, the card is half out of frame, and the person tries again or gives up. Getting capture right is mainly a user experience problem, and it’s the same problem for every team that builds one of these flows. We’d rather share our answer than have everyone rebuild it from scratch.
What’s in it
- Document capture. Maps the on-screen guide onto the camera frame, even when the preview is cropped to fill the screen. Scores blur, glare, edges, brightness and hand shake, notices when a face is held up instead of a card, and captures automatically after a steady hold. The guidance is plain: “Tilt to reduce glare”, not an error code.
- Guided face poses. Centre, turn left and right, blink and smile, using Google’s MediaPipe Face Landmarker in the browser. The hold timer tolerates a momentary flicker instead of starting again.
- Feedback cues. Synthesised tones, short spoken prompts and vibration, with a mute switch that is remembered.
- MRZ parsing. Reads the machine-readable zone on passports (ICAO 9303) with strict check digits, plus the dates on UK photocard driving licences.
- Camera helpers. Sensible fallbacks when a camera rejects the preferred settings, inline playback on iOS, and error messages written for people rather than developers.
The core has no framework dependency. Optional React hooks are included for teams that want them.
Sound, because you can’t see the screen
Turning your head means looking away from the screen, so a visual prompt telling you to hold still arrives at exactly the moment you can’t see it. So every step has a sound. A soft tick says the toolkit has locked on, a rising chime says the step is captured, and a short spoken prompt tells you what to do next. On phones that support it, there’s a brief vibration too. Safari on iOS doesn’t support vibration, so there it’s sound only. If you’d rather work in silence, mute it once and it stays muted.
Strict about passports
The two lines of characters at the bottom of a passport’s photo page carry check digits: small sums that confirm the document number, date of birth and expiry date were read correctly. By default, the parser accepts a reading only when every check digit passes.
There is a relaxed mode, for live “we can read it” feedback while someone is still lining up the document. It’s opt-in and documented as such. Either way, check digits catch misreads, not forgeries. Anyone can calculate them.
On the device, and not a security boundary
Every check runs in the browser on a small, downscaled copy of the camera frame. The library uploads nothing on its own: you decide which captured photos, if any, leave the device. By default the face model is fetched from public CDNs, and you can host those files yourself instead.
Just as important is what the toolkit cannot do. Code running in someone’s browser can’t prove that a document is genuine or that a live person is in front of the camera. JavaScript can be modified, cameras can be virtual and video can be replayed. So treat every quality score, ready flag and parsed field as a hint for the person holding the phone, never as a verdict.
In Veriwell, the decisions that matter, such as document checks, liveness and face matching, happen on our servers, on the uploaded images, against our own thresholds. If you build on veriwell-capture, do the same.
Get it
The source, documentation and a plain HTML demo are on GitHub. It works in recent versions of Chrome, Edge, Firefox and Safari on desktop, Android and iOS. Camera access needs HTTPS.
Issues and pull requests are welcome. Please report security problems privately, as described in the repository’s security policy. veriwell-capture is made by the team behind Veriwell.