react-html5-camera-photo and react-webcam are both React components designed to access the user's camera via the browser's getUserMedia API, but they serve distinct primary purposes. react-html5-camera-photo is specialized for taking high-quality still photos, offering built-in features like face detection, image orientation correction, and immediate capture callbacks. It focuses on the single action of snapping a picture and returning the data. react-webcam, on the other hand, is built for continuous video streaming and monitoring. It excels at rendering a live video feed, capturing individual frames from that stream on demand, and supports advanced constraints like specific resolutions and aspect ratios. While there is some overlap, one is optimized for a "photo booth" experience, and the other for a "video feed" experience.
When integrating camera functionality into a React application, developers often face a choice between specialized tools. react-html5-camera-photo and react-webcam both tap into the browser's media devices, but they solve different problems. One is engineered for snapping high-quality still images with minimal fuss, while the other is designed for rendering and managing continuous video feeds. Understanding these distinctions is critical for selecting the right tool for your specific user experience goals.
The fundamental difference lies in what each library optimizes for. react-html5-camera-photo treats the camera as a scanner. Its lifecycle is geared towards waiting for a trigger, capturing a single frame, processing it, and handing off the result. It abstracts away the video element's continuous rendering unless explicitly needed for preview.
In contrast, react-webcam treats the camera as a video source. It renders a <video> element that stays active, updating constantly. You use it when the user needs to see themselves moving in real-time, or when you need to grab frames at irregular intervals.
// react-html5-camera-photo: Focuses on the 'onTakePhoto' event
import Camera from 'react-html5-camera-photo';
function PhotoBooth() {
const handleTakePhoto = (dataUri) => {
console.log("Photo captured:", dataUri);
// Immediate base64 string ready for upload
};
return (
<Camera
onTakePhoto={handleTakePhoto}
idealFacingMode="user"
/>
);
}
// react-webcam: Focuses on the continuous video stream
import Webcam from "react-webcam";
function VideoPreview() {
const webcamRef = React.useRef(null);
return (
<Webcam
ref={webcamRef}
audio={true}
videoConstraints={{ width: 1280, height: 720 }}
/>
);
}
One of the most painful issues in web camera development is image orientation. Mobile browsers often report landscape coordinates even when the phone is held vertically, resulting in sideways photos. react-html5-camera-photo solves this out of the box. It automatically detects the device orientation and rotates the captured image data so it appears correct to the user.
react-webcam does not perform this automatic correction on captured screenshots. If you capture a frame using getScreenshot(), you get the raw pixel data from the video element. If the video stream itself is rotated by the browser, your screenshot will be too. You would need to write custom canvas manipulation code to fix this.
// react-html5-camera-photo: Auto-corrects orientation internally
// No extra code needed; the dataUri returned is always upright
<Camera
onTakePhoto={(dataUri) => {
// dataUri is guaranteed to be oriented correctly
uploadImage(dataUri);
}}
/>
// react-webcam: Raw capture requires manual orientation handling
const capture = React.useCallback(() => {
const imageSrc = webcamRef.current.getScreenshot();
// WARNING: imageSrc might be sideways on mobile devices
// Developer must manually rotate using HTML5 Canvas if needed
}, [webcamRef]);
For security-sensitive flows like KYC (Know Your Customer) or identity verification, knowing that a real human is in front of the camera is vital. react-html5-camera-photo includes a built-in face detection feature. It can prevent the photo capture function from firing if no face is detected, or it can report the status continuously.
react-webcam has no concept of image content analysis. It simply streams pixels. Implementing face detection with react-webcam requires you to export frames to a canvas, run them through a separate library like face-api.js or clmtrackr, and manage the synchronization yourself. This adds significant complexity and potential performance overhead.
// react-html5-camera-photo: Built-in face detection
<Camera
onTakePhoto={(dataUri) => { /* ... */ }}
onDetectFace={(face) => {
if (face) {
console.log("Face detected at:", face);
} else {
console.log("No face found, disable capture button");
}
}}
/>
// react-webcam: No built-in detection; requires external logic
// You must manually extract frames and run a detection model
const checkForFace = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.drawImage(webcamRef.current.video, 0, 0);
// Now pass 'canvas' to an external face detection library
// This loop must be managed manually by the developer
};
When you need precise control over the video stream quality, react-webcam offers a more direct mapping to the MediaStreamConstraints API. You can pass a videoConstraints object that strictly defines width, height, aspect ratio, and frame rate. This is essential for applications that require specific resolutions for downstream processing.
react-html5-camera-photo allows some configuration via idealFacingMode and imageFormat, but it is less granular regarding stream constraints. It prioritizes getting a good photo over configuring the underlying video stream parameters.
// react-html5-camera-photo: Limited constraint options
<Camera
idealFacingMode="environment" // Rear camera
imageFormat="png"
isSilentMode={false}
/>
// react-webcam: Full constraint control
<Webcam
videoConstraints={{
width: 1920,
height: 1080,
aspectRatio: 16/9,
frameRate: 30,
facingMode: "user"
}}
/>
Switching between front and rear cameras is a common requirement. react-webcam handles this gracefully by accepting new props. If you change the videoConstraints or deviceId, the component automatically stops the old stream and initializes the new one. This makes it very easy to build a UI with a "Flip Camera" button.
react-html5-camera-photo also supports switching via the idealFacingMode prop, but because its primary goal is a single capture, the reactivity model is slightly less focused on continuous stream management. However, for standard front/back switching, both packages function adequately.
// react-webcam: Dynamic device switching
const [deviceId, setDeviceId] = useState(undefined);
// When deviceId changes, the video stream updates automatically
<Webcam
videoConstraints={{
deviceId: deviceId ? { exact: deviceId } : undefined
}}
/>
// react-html5-camera-photo: Switching facing mode
const [facingMode, setFacingMode] = useState("user");
// Toggles between 'user' and 'environment'
<Camera
idealFacingMode={facingMode}
onTakePhoto={handleTakePhoto}
/>
Despite their different focuses, both libraries share core characteristics that make them viable for React projects.
Both packages rely on the standard browser navigator.mediaDevices.getUserMedia API. This means they work in any modern browser that supports WebRTC without needing plugins.
// Both internally call something similar to:
navigator.mediaDevices.getUserMedia({ video: true });
Both libraries ultimately provide image data as a Base64 encoded string (Data URI). This makes it trivial to display the result in an <img> tag or send it directly to a server API.
// Both produce strings starting with "data:image/png;base64,..."
<img src={capturedDataUri} alt="Capture" />
Both are implemented as standard functional or class components that fit naturally into the React render cycle. They handle the messy imperative video API code internally, exposing clean props and callbacks.
| Feature | react-html5-camera-photo | react-webcam |
|---|---|---|
| Primary Use Case | Taking single, high-quality photos | Streaming live video |
| Image Orientation | ✅ Auto-corrects mobile rotation | ❌ Raw output (manual fix needed) |
| Face Detection | ✅ Built-in support | ❌ Requires external library |
| Video Constraints | ⚠️ Basic (facing mode) | ✅ Advanced (resolution, FPS, aspect) |
| Capture Method | Event-driven (onTakePhoto) | Manual (getScreenshot()) |
| Stream Management | Optimized for single capture | Optimized for continuous play |
Choosing between these two comes down to your end goal. If you are building a profile picture uploader, a document scanner, or any flow where the user needs to take one good photo and you want to avoid mobile orientation bugs, react-html5-camera-photo is the clear winner. Its built-in face detection and auto-rotation save weeks of debugging.
If you are building a video chat app, a security monitor, or a tool where the user needs to watch the feed and capture frames occasionally, react-webcam is the superior choice. Its granular control over video constraints and seamless stream switching makes it the robust option for continuous media experiences.
Choose react-html5-camera-photo if your primary goal is to build a photo-taking interface, such as a profile picture uploader or a document scanner. This package handles the complexities of image orientation (fixing upside-down photos from mobile devices) and provides immediate access to the base64 image data upon capture. It is the superior choice when you need to detect faces to ensure the user is present before allowing a capture, as it includes built-in face detection logic that react-webcam lacks.
Choose react-webcam if you need to display a continuous live video stream or require fine-grained control over video constraints like specific aspect ratios, minimum frame rates, or exact resolution settings. This package is ideal for video conferencing previews, security monitoring dashboards, or scenarios where you need to capture multiple frames programmatically over time rather than a single snapshot. It is also the better option if you need to switch between multiple camera devices dynamically while the stream is active.
The first objective of this package comes from the need to get the same look and feel of a native mobile camera app but with a react component.
For those who want to build with their own css and need an abstraction of getUserMedia() take a look of jslib-html5-camera-photo with react.

Demo of react-html5-camera-photo
https or localhost : The getUserMedia() method is only available in secure contexts (https or localhost). If a document isn't loaded in a secure context, the navigator.mediaDevices property is undefined, making access to getUserMedia() impossible. Attempting to access getUserMedia() in this situation will result in a TypeError. See developer.mozilla.org
iOS >= 11 WebRTC issue with webkit (Chrome & Firefox) : Apple restricts WebRTC to Safari only so it mean that you can't use the getUserMedia() with Firefox and Chrome. So getUserMedia() is not supported yet, for "security reasons". See Stackoverflow
npm install --save react-html5-camera-photo
yarn add react-html5-camera-photo
TypeScript definitions are available from Definitely Typed
npm install --save-dev @types/react-html5-camera-photo
yarn add --dev @types/react-html5-camera-photo
| parameter | Description |
|---|---|
| onTakePhoto(dataUri): | Event function called when a photo is taken. the dataUri is passed as a parameter. |
Minimum ES6 example
import React from 'react';
import Camera from 'react-html5-camera-photo';
import 'react-html5-camera-photo/build/css/index.css';
function App (props) {
function handleTakePhoto (dataUri) {
// Do stuff with the photo...
console.log('takePhoto');
}
return (
<Camera
onTakePhoto = { (dataUri) => { handleTakePhoto(dataUri); } }
/>
);
}
export default App;
| Properties | Type | Default | Description |
|---|---|---|---|
| onCameraStart(): (optional) | Event | Callback called when the camera is started. | |
| onCameraStop(): (optional) | Event | Callback called when the camera is stopped. | |
| onCameraError(error): (Optional) | Event | Callback called with the error object as parameter when error occur while opening the camera. Often the permission. | |
| onTakePhoto(dataUri): (Optional) | Event | The function called when a photo is taken. the dataUri is passed as a parameter. | |
| onTakePhotoAnimationDone(dataUri): (Optional) | Event | The function called when a photo is taken and the animation is done. the dataUri is passed as a parameter. | |
| idealFacingMode: (Optional) (Dynamic) | String | Browser default | The ideal facing mode of the camera, environment or user. Use FACING_MODES constant to get the right string. Example :. FACING_MODES.ENVIRONMENT or FACING_MODES.USER |
| idealResolution: (Optional) (Dynamic) | Object | Browser default | Object of the ideal resolution of the camera, {width: Integer, height: Integer}. |
| isMaxResolution: (Optional) (Dynamic) | Boolean | false | If is true, the camera will start with his own maximum resolution. |
| isImageMirror: (Optional) | Boolean | true | If is true, the camera image will be mirror. |
| isSilentMode:(Optional) | Boolean | false | If is true, the camera do not play click sound when the photo was taken. |
| isFullscreen: (Optional) | Boolean | false | If is true, the camera image will be set fullscreen to force the maximum width and height of the viewport. |
| isDisplayStartCameraError: (Optional) | Boolean | true | If is true, if the camera start with error, it will show the error between h1 tag on the top of the component. Useful to notify the user about permission error. |
| sizeFactor: (Optional) | Number | 1 | Number of the factor resolution. Example, a sizeFactor of 1 get the same resolution of the camera while sizeFactor of 0.5 get the half resolution of the camera. The sizeFactor can be between range of ]0, 1]. |
| imageType:: (Optional) | String | png | String used to get the desired image type between jpg or png. to specify the imageType use the constant IMAGE_TYPES, for example to specify jpg format use IMAGE_TYPES.JPG. Use IMAGE_TYPES constant to get the right image type Example:. IMAGE_TYPES.JPG or IMAGE_TYPES.PNG |
| imageCompression:: (Optional) | Number | 0.92 | Number used to get the desired compression when jpg is selected. choose a compression between [0, 1], 1 is maximum, 0 is minimum. |
Dynamic : If the prop is dynamic, it mean that you can change that prop dynamically without umount the component (removing it). You can do it by a setState() inside the parent component. Checkout the demo example: ./src/demo/AppWithDynamicProperties.js
Probably the typical usage of using this component is to preview the image and close the camera after take a photo. You can take a look of all the code including the ImagePreview component here : ./src/demo/AppWithImagePreview
import React, { useState } from 'react';
import Camera from 'react-html5-camera-photo';
import 'react-html5-camera-photo/build/css/index.css';
import ImagePreview from './ImagePreview'; // source code : ./src/demo/AppWithImagePreview/ImagePreview
function App (props) {
const [dataUri, setDataUri] = useState('');
function handleTakePhotoAnimationDone (dataUri) {
console.log('takePhoto');
setDataUri(dataUri);
}
const isFullscreen = false;
return (
<div>
{
(dataUri)
? <ImagePreview dataUri={dataUri}
isFullscreen={isFullscreen}
/>
: <Camera onTakePhotoAnimationDone = {handleTakePhotoAnimationDone}
isFullscreen={isFullscreen}
/>
}
</div>
);
}
export default App;
import React from 'react';
import Camera, { FACING_MODES, IMAGE_TYPES } from 'react-html5-camera-photo';
import 'react-html5-camera-photo/build/css/index.css';
function App (props) {
function handleTakePhoto (dataUri) {
// Do stuff with the photo...
console.log('takePhoto');
}
function handleTakePhotoAnimationDone (dataUri) {
// Do stuff with the photo...
console.log('takePhoto');
}
function handleCameraError (error) {
console.log('handleCameraError', error);
}
function handleCameraStart (stream) {
console.log('handleCameraStart');
}
function handleCameraStop () {
console.log('handleCameraStop');
}
return (
<Camera
onTakePhoto = { (dataUri) => { handleTakePhoto(dataUri); } }
onTakePhotoAnimationDone = { (dataUri) => { handleTakePhotoAnimationDone(dataUri); } }
onCameraError = { (error) => { handleCameraError(error); } }
idealFacingMode = {FACING_MODES.ENVIRONMENT}
idealResolution = {{width: 640, height: 480}}
imageType = {IMAGE_TYPES.JPG}
imageCompression = {0.97}
isMaxResolution = {true}
isImageMirror = {false}
isSilentMode = {false}
isDisplayStartCameraError = {true}
isFullscreen = {false}
sizeFactor = {1}
onCameraStart = { (stream) => { handleCameraStart(stream); } }
onCameraStop = { () => { handleCameraStop(); } }
/>
);
}
export default App;
Before sending a bug report of camera error, make sure that getUserMedia() is supported by your browser. Please test your camera on : DetectRTC | Is WebRTC Supported In Your Browser? If the System has Webcam is supported, please send the screenshot of the first 7 first rows of the table.