ImageCapture.takePhoto() Demonstrator
Open your camera, take a full-resolution still photo using the
ImageCapture.takePhoto() API, inspect every piece of metadata
the browser exposes, and download the result.
Privacy: Everything runs locally in your browser. No images or data leave your device.
Tip: On phones, the rear camera typically exposes much higher resolution via takePhoto() than the video preview resolution.
takePhoto() vs grabFrame() -- What is the Difference?
The ImageCapture API provides two methods for obtaining an image from a camera stream. They serve very different purposes and produce different outputs.
| takePhoto() | grabFrame() | |
|---|---|---|
| What it does | Triggers the camera's full still-image capture pipeline, just like pressing a hardware shutter button | Grabs the current frame from the live video track |
| Output type | Blob (typically JPEG) |
ImageBitmap |
| Resolution | Full sensor resolution (e.g. 12MP, 48MP, 108MP) -- independent of the video stream constraints | Matches the video track resolution (e.g. 1280x720, 1920x1080) |
| Speed | Slower -- may involve autofocus lock, auto-exposure, sensor readout at full res | Very fast -- just copies the current decoded frame |
| Camera flash | Can trigger the flash via PhotoSettings.fillLightMode | No flash support |
| Red-eye reduction | Supported (if hardware allows) | Not available |
| Image processing | Full ISP pipeline: noise reduction, HDR, sharpening, tone mapping | Uses the video encode path, which is optimized for speed over quality |
| Use case | When you need a high-quality still photograph | When you need to process video frames in real-time (barcode scanning, CV, effects) |
| Interrupts video? | May briefly pause the video stream during capture | No interruption at all |
| Metadata available | EXIF data may be embedded in the JPEG Blob (browser/OS dependent) | No embedded metadata -- just raw pixel data |
When to use takePhoto()
- Document scanning where detail matters
- Product photography
- Any time you want the highest resolution the sensor can deliver
- When you need flash support
- When the user explicitly presses a "capture" button
When to use grabFrame()
- Real-time computer vision (face detection, barcode scanning)
- Video effects / filters applied per-frame
- Motion detection
- Timelapse where speed matters more than maximum resolution
- Any continuous frame-by-frame processing loop
Understanding the Metadata
MediaTrackSettings
These are the actual negotiated settings of the video track. They tell you what resolution the camera is streaming at, the frame rate, the facing mode, aspect ratio, and device ID. The video stream resolution is typically lower than the sensor maximum because it needs to encode frames in real time.
MediaTrackCapabilities
This object describes the full ranges the hardware supports: minimum and maximum width/height, frame rate ranges, supported facing modes, zoom levels, torch mode, and more. This is what the camera could do, not what it is currently doing.
PhotoCapabilities
Specific to still capture. Reports the range of resolutions available for takePhoto(), supported fill light modes (flash), and red-eye reduction capability. The maximum width/height here is typically much larger than the video stream dimensions because the still pipeline accesses the full sensor.
PhotoSettings
The current configuration that will be used when takePhoto() is called. Includes image width/height, fill light mode, and red-eye reduction setting. You can override these by passing a PhotoSettings object to takePhoto().
Photo Blob Metadata
After capture, the Blob itself carries the MIME type, byte size, and when decoded into an Image element, we can read the actual pixel dimensions. Comparing the Blob dimensions to the video stream dimensions shows you exactly how much more resolution takePhoto() provides.
Browser Support
The ImageCapture API is a living standard maintained by the W3C. Support varies:
| Browser | takePhoto() | grabFrame() | PhotoCapabilities |
|---|---|---|---|
| Chrome (Android) | Yes (since v59) | Yes | Yes |
| Chrome (Desktop) | Yes (since v59) | Yes | Yes |
| Edge | Yes (Chromium-based) | Yes | Yes |
| Samsung Internet | Yes | Yes | Yes |
| Opera | Yes | Yes | Yes |
| Safari (iOS/macOS) | Partial (recent versions) | Partial | Limited |
| Firefox | Behind flag | Behind flag | No |
If ImageCapture is not available, this tool will show you a clear error. Using Chrome on Android gives the best experience with full PhotoCapabilities reporting.
Frequently Asked Questions
What is the ImageCapture API?
The ImageCapture API is a browser standard that gives JavaScript direct control over camera hardware. It lets you take full-resolution still photos (via takePhoto()) independent of the video stream resolution, and read or set camera parameters like ISO, white balance, exposure, zoom, and focus.
What is the difference between takePhoto() and grabFrame()?
takePhoto() triggers the camera's full still-image pipeline, producing a high-resolution Blob (often JPEG) at the sensor's maximum capability. grabFrame() simply grabs the current video frame as an ImageBitmap at the video track's resolution. takePhoto() is slower but produces much higher quality images.
Which browsers support the ImageCapture API?
As of 2026, ImageCapture is supported in Chromium-based browsers (Chrome, Edge, Opera, Samsung Internet) on desktop and Android. Safari on iOS and macOS has partial support. Firefox has limited support behind flags.
Why is the photo resolution higher than the video preview?
The video stream typically runs at a lower resolution for performance (e.g. 1280x720 or 1920x1080). takePhoto() bypasses the video pipeline and captures directly from the image sensor at its full native resolution, which can be 12MP, 48MP, or even higher on modern phones.
Is my photo uploaded anywhere?
No. Everything runs locally in your browser. The camera stream, the captured photo, and all metadata inspection happen entirely on your device. Nothing is sent to any server.
Can I control flash or zoom from this tool?
This demonstrator requests takePhoto() at maximum resolution with default settings. The PhotoCapabilities dump will show you whether your camera supports flash, zoom, torch, and other features. A production app could pass custom PhotoSettings to control all of these.
Why does the captured photo look different from the preview?
The still capture pipeline applies different processing than the video path. The camera may perform additional noise reduction, HDR merging, sharpening, and tone mapping when taking a still photo. This is normal and is the same difference you see between a phone's viewfinder and the final saved photo.
Related Tools
- Aquarium Volume Calculator -- Calculate aquarium water volume and weight for rectangular, bow-front, and
- Concrete Footing Calculator -- Calculate concrete volume, bags, and cost for continuous, pier, and spread
- Vibration Frequency Analyzer -- Measure vibration frequency using your phone's accelerometer
- Board Foot Calculator -- Calculate board feet of lumber from thickness, width, and length with cost
Related Tools
View all toolsSquare Footage Calculator
Calculate area in square feet from room dimensions for flooring, painting, and more
Tip Calculator
Calculate tip amount, total, and per-person split
Online Compass
Digital compass using your device's magnetometer sensor
Split Bill Calculator
Split a total evenly across a group
Receipt Total Calculator
Add line items, tax, discounts, tip, and split totals instantly
Shopping List Builder
Build a smart shopping list with quantities, categories, and budget tracking
ImageCapture takePhoto() Demonstrator FAQ
What is the ImageCapture API?
The ImageCapture API is a browser standard that gives JavaScript direct control over camera hardware. It lets you take full-resolution still photos (via takePhoto()) independent of the video stream resolution, and read or set camera parameters like ISO, white balance, exposure, zoom, and focus.
What is the difference between takePhoto() and grabFrame()?
takePhoto() triggers the camera's full still-image pipeline, producing a high-resolution Blob (often JPEG) at the sensor's maximum capability. grabFrame() simply grabs the current video frame as an ImageBitmap at the video track's resolution. takePhoto() is slower but produces much higher quality images.
Which browsers support the ImageCapture API?
As of 2026, ImageCapture is supported in Chromium-based browsers (Chrome, Edge, Opera, Samsung Internet) on desktop and Android. Safari on iOS and macOS has partial support. Firefox has limited support behind flags.
Why is the photo resolution higher than the video preview?
The video stream typically runs at a lower resolution for performance (e.g. 1280x720 or 1920x1080). takePhoto() bypasses the video pipeline and captures directly from the image sensor at its full native resolution, which can be 12MP, 48MP, or even higher on modern phones.
Is my photo uploaded anywhere?
No. Everything runs locally in your browser. The camera stream, the captured photo, and all metadata inspection happen entirely on your device. Nothing is sent to any server.