About this webcam test
A small, dependency-free tool for one job: opening your camera through the browser's own API and showing you exactly what it actually granted, not just what you asked for. No account, no upload, nothing recorded.
Why it exists
Checking a camera usually means opening whatever app you plan to use it in and hoping the preview looks right. That tells you very little about what the camera is actually doing: the resolution you requested is frequently not the resolution you get, "30fps" in a spec sheet is a nominal figure the hardware can and does miss under bad lighting, and most apps never surface the device's real settings at all. This page asks the browser directly, via the same getUserMedia API every video-call app already uses, and reports the numbers it gets back rather than the ones you typed in.
How it is built
navigator.mediaDevices.getUserMedia({ video: … })opens the stream. Resolution presets are sent asidealconstraints, neverexact— an exact constraint a camera cannot satisfy makes the whole call fail, while an ideal constraint lets the browser substitute its closest supported mode and still hand back a usable stream.- Live stats come from two places.
video.videoWidth/video.videoHeightgive the actual decoded frame size once the stream's metadata has loaded, and the video track's owngetSettings()gives the negotiated frame rate, aspect ratio and device ID as the driver reports them. - Measured frame rate is timed, not reported. Where the browser supports
requestVideoFrameCallback, this page timestamps real decoded frames as they arrive and computes an actual rate from the gaps between them, shown next to the driver's nominal figure so you can see whether they agree. - The device picker comes from
navigator.mediaDevices.enumerateDevices(), filtered tovideoinputkind. Camera labels only appear once a permission has been granted at least once in the session — that is a browser privacy behaviour, not something this page controls. - The snapshot draws the current video frame onto a
<canvas>element with the 2D drawing context, thencanvas.toBlob()produces a PNG that becomes a downloadable object URL. The canvas never leaves the page unless you click Download. - Vanilla JavaScript, one small stylesheet, no framework, no build step, no network request other than loading this page.
What "nothing is uploaded" actually means here
This page never opens a network connection to send video anywhere — there is no server component behind the camera preview or the snapshot at all. You can verify this yourself: open your browser's developer tools, switch to the Network panel, start the camera, take a snapshot, and watch the request list. It stays empty for anything related to the camera. The only network activity on this page is the original page load itself.
Scope and honesty about limits
This tool reports what the browser's camera API reports. It cannot judge image sharpness, colour accuracy or low-light noise — those need a human eye or a proper camera-review benchmark, not a getSettings() call. The "requested" frame rate is the driver's own negotiated figure, not a promise the hardware keeps under every lighting condition, which is exactly why the measured figure exists alongside it. And because every browser tab negotiates with the camera driver independently, the numbers here describe this page's own session — they are a good proxy for, but not a guarantee of, what another app will get when it opens the same camera.
If you find a case where this page's numbers look wrong compared with what your operating system's own camera settings report, that is worth reporting — see contact.