LLM Guides

How to Detect Faces in a Video with JavaScript

Jun 29, 2026

Face detection in video sounds like a small feature until you start building it.

A camera opens. A person moves. The lighting changes. The face turns sideways. The browser drops frames. Mobile devices get hot. Suddenly, “draw a box around a face” becomes a real-time computer vision problem.

The good news: JavaScript can handle it. You can detect faces directly in the browser with modern web APIs and machine learning models. You can use the user’s webcam, process video frame by frame, draw boxes on a canvas, and build useful features without sending every frame to a server.

This guide shows how to detect faces in a video with JavaScript, what tools you can use, and which approach makes the most sense for different teams.

We’ll cover:

  • Browser camera access with JavaScript
  • Face detection with MediaPipe
  • How to draw bounding boxes over video
  • How MediaPipe compares with TensorFlow.js, face-api.js, native browser APIs, and server-side APIs
  • What businesses, developers, creators, and product teams can build with face detection
  • Privacy, performance, and testing tips

What Face Detection Means

Face detection finds where faces appear in an image or video frame.

It usually returns:

OutputMeaning
Bounding boxThe face location in the frame
Confidence scoreHow sure the model is
KeypointsPoints like eyes, nose, or mouth, depending on the model
Multiple detectionsAll faces found in the frame

Face detection does not automatically identify who the person is. That would be face recognition. Detection answers: “Is there a face here, and where is it?”

That distinction matters for privacy and product design. A video app that uses face detection to keep a speaker centered is very different from an app that identifies people by name.

Which JavaScript Face Detection Approach Should You Use?

There are several ways to detect faces in video with JavaScript.

ApproachBest forMain benefitWatch out for
MediaPipe Face DetectorReal-time browser appsFast, modern, browser-friendlyRequires model setup
TensorFlow.js face detectionDevelopers already using TensorFlow.jsFlexible ML ecosystemMore model/runtime choices to manage
face-api.jsDemos and older projectsPopular and easy to understandMaintenance and model age need review
Native FaceDetector APISimple browser-native experimentsNo external model packageLimited browser support
Server-side APICompliance, storage, backend processingCentralized processingLatency and privacy concerns

For most new JavaScript projects, MediaPipe Face Detector is the best first choice. Google’s MediaPipe Face Detector docs describe it as a model for detecting faces in images and video. It works well for real-time web experiences.

Why We Can Write About This

Our team has worked with AI APIs, developer tools, computer vision workflows, and web automation for around 6 years. For this guide, we reviewed current browser docs, MediaPipe documentation, TensorFlow.js resources, and face detection research.

The research matters because face detection has a long technical history. The classic Viola-Jones paper helped popularize real-time face detection in the early 2000s. More recent models like BlazeFace were designed for fast face detection on mobile GPUs. That is the kind of work behind modern browser-friendly face detection.

Step 1: Create the HTML

We’ll build a simple page with:

  • A video element for the webcam feed
  • A canvas overlay for face boxes
  • A button to start the camera
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Face Detection in Video</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      background: #111827;
      color: white;
      display: flex;
      justify-content: center;
      padding: 40px;
    }

    .app {
      width: 720px;
    }

    .video-wrap {
      position: relative;
      width: 720px;
      height: 405px;
      background: #000;
      overflow: hidden;
      border-radius: 8px;
    }

    video,
    canvas {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
    }

    canvas {
      pointer-events: none;
    }

    button {
      margin-top: 16px;
      padding: 10px 14px;
      border: 0;
      border-radius: 6px;
      cursor: pointer;
      font-weight: 600;
    }

    #status {
      margin-top: 12px;
      color: #d1d5db;
    }
  </style>
</head>
<body>
  <div class="app">
    <h1>Face Detection in Video</h1>

    <div class="video-wrap">
      <video id="video" autoplay playsinline muted></video>
      <canvas id="canvas"></canvas>
    </div>

    <button id="startButton">Start camera</button>
    <p id="status">Camera is off.</p>
  </div>

  <script type="module" src="./app.js"></script>
</body>
</html>

This gives us a clean base. The video shows the webcam. The canvas sits on top and draws the detected face boxes.

Step 2: Access the Camera

The browser camera comes from navigator.mediaDevices.getUserMedia().

MDN’s getUserMedia documentation explains that it asks the user for access to media devices, such as a camera or microphone. In most browsers, this works only on HTTPS or localhost.

Create an app.js file:

const video = document.getElementById("video");
const canvas = document.getElementById("canvas");
const statusText = document.getElementById("status");
const startButton = document.getElementById("startButton");

const ctx = canvas.getContext("2d");

async function startCamera() {
  const stream = await navigator.mediaDevices.getUserMedia({
    video: {
      width: 720,
      height: 405,
      facingMode: "user"
    },
    audio: false
  });

  video.srcObject = stream;

  await new Promise((resolve) => {
    video.onloadedmetadata = resolve;
  });

  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;

  statusText.textContent = "Camera is running.";
}

startButton.addEventListener("click", async () => {
  try {
    await startCamera();
  } catch (error) {
    console.error(error);
    statusText.textContent = "Could not access camera.";
  }
});

At this point, the browser can show webcam video. Next, we add face detection.

Step 3: Add MediaPipe Face Detector

MediaPipe provides ready-to-use vision models for the web. The current MediaPipe Tasks Vision package can run models in the browser through WebAssembly and GPU acceleration when available.

Install with npm:

npm install @mediapipe/tasks-vision

For a quick browser demo, you can also import from a CDN.

Update app.js:

import {
  FaceDetector,
  FilesetResolver
} from "https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]";

const video = document.getElementById("video");
const canvas = document.getElementById("canvas");
const statusText = document.getElementById("status");
const startButton = document.getElementById("startButton");

const ctx = canvas.getContext("2d");

let faceDetector;
let lastVideoTime = -1;

async function createFaceDetector() {
  const vision = await FilesetResolver.forVisionTasks(
    "https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/wasm"
  );

  faceDetector = await FaceDetector.createFromOptions(vision, {
    baseOptions: {
      modelAssetPath:
        "https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/latest/blaze_face_short_range.tflite",
      delegate: "GPU"
    },
    runningMode: "VIDEO"
  });
}

This loads the MediaPipe face detector model. The runningMode: “VIDEO” option tells MediaPipe that we will process a stream over time, not a single still image.

Step 4: Detect Faces Frame by Frame

Now we need a loop.

The browser gives us video frames. MediaPipe checks each frame. Canvas draws the boxes.

Add this function:

function drawDetections(detections) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  for (const detection of detections) {
    const box = detection.boundingBox;

    ctx.strokeStyle = "#22c55e";
    ctx.lineWidth = 3;
    ctx.strokeRect(
      box.originX,
      box.originY,
      box.width,
      box.height
    );

    const score = detection.categories?.[0]?.score ?? 0;

    ctx.fillStyle = "#22c55e";
    ctx.font = "16px Arial";
    ctx.fillText(
      `Face ${(score * 100).toFixed(1)}%`,
      box.originX,
      Math.max(box.originY - 8, 20)
    );
  }
}

function detectFaces() {
  if (!faceDetector || video.readyState < 2) {
    requestAnimationFrame(detectFaces);
    return;
  }

  if (video.currentTime !== lastVideoTime) {
    lastVideoTime = video.currentTime;

    const startTimeMs = performance.now();
    const result = faceDetector.detectForVideo(video, startTimeMs);

    drawDetections(result.detections);
  }

  requestAnimationFrame(detectFaces);
}

Then update the button handler:

startButton.addEventListener("click", async () => {
  try {
    statusText.textContent = "Loading face detector...";

    await createFaceDetector();
    await startCamera();

    statusText.textContent = "Detecting faces.";
    detectFaces();
  } catch (error) {
    console.error(error);
    statusText.textContent = "Could not start face detection.";
  }
});

Now the app can:

Open camera → Read video frame → Detect faces with MediaPipe → Draw bounding boxes on canvas → Repeat in real time

Full JavaScript Example

Here is the full app.js in one place:

import {
  FaceDetector,
  FilesetResolver
} from "https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]";

const video = document.getElementById("video");
const canvas = document.getElementById("canvas");
const statusText = document.getElementById("status");
const startButton = document.getElementById("startButton");

const ctx = canvas.getContext("2d");

let faceDetector;
let lastVideoTime = -1;

async function createFaceDetector() {
  const vision = await FilesetResolver.forVisionTasks(
    "https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/wasm"
  );

  faceDetector = await FaceDetector.createFromOptions(vision, {
    baseOptions: {
      modelAssetPath:
        "https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/latest/blaze_face_short_range.tflite",
      delegate: "GPU"
    },
    runningMode: "VIDEO"
  });
}

async function startCamera() {
  const stream = await navigator.mediaDevices.getUserMedia({
    video: {
      width: 720,
      height: 405,
      facingMode: "user"
    },
    audio: false
  });

  video.srcObject = stream;

  await new Promise((resolve) => {
    video.onloadedmetadata = resolve;
  });

  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
}

function drawDetections(detections) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  for (const detection of detections) {
    const box = detection.boundingBox;
    const score = detection.categories?.[0]?.score ?? 0;

    ctx.strokeStyle = "#22c55e";
    ctx.lineWidth = 3;
    ctx.strokeRect(box.originX, box.originY, box.width, box.height);

    ctx.fillStyle = "#22c55e";
    ctx.font = "16px Arial";
    ctx.fillText(
      `Face ${(score * 100).toFixed(1)}%`,
      box.originX,
      Math.max(box.originY - 8, 20)
    );
  }
}

function detectFaces() {
  if (!faceDetector || video.readyState < 2) {
    requestAnimationFrame(detectFaces);
    return;
  }

  if (video.currentTime !== lastVideoTime) {
    lastVideoTime = video.currentTime;

    const result = faceDetector.detectForVideo(
      video,
      performance.now()
    );

    drawDetections(result.detections);
  }

  requestAnimationFrame(detectFaces);
}

startButton.addEventListener("click", async () => {
  try {
    statusText.textContent = "Loading face detector...";

    await createFaceDetector();
    await startCamera();

    statusText.textContent = "Detecting faces.";
    detectFaces();
  } catch (error) {
    console.error(error);
    statusText.textContent = "Could not start face detection.";
  }
});

MediaPipe vs TensorFlow.js vs face-api.js

You have several options for face detection in JavaScript. Here is the practical comparison.

ToolBest forStrengthWeakness
MediaPipe Face DetectorModern real-time browser appsFast and maintained by GoogleSetup feels more detailed at first
TensorFlow.js face detectionML-heavy JavaScript appsFlexible model ecosystemMore choices to manage
face-api.jsSimple demos and older tutorialsEasy examples and familiar APICheck maintenance before production
Native FaceDetector APIExperiments in supported browsersBrowser-native ideaLimited browser support
Server-side APIBackend workflowsCentral control and storageMore latency and privacy review

When MediaPipe Is the Best Choice

Use MediaPipe when you need real-time detection in the browser.

Good use cases:

Use caseWhy MediaPipe fits
Video filtersFast local detection
Camera framingWorks in real time
Virtual try-onNeeds face position quickly
Creator toolsRuns without uploading every frame
Browser demosStrong model quality with manageable setup

MediaPipe is also a good fit for mobile browsers because models like BlazeFace were designed for fast face detection on devices. The BlazeFace paper describes a lightweight face detector made for mobile GPU inference, which is exactly the kind of design that helps with browser camera apps.

When TensorFlow.js Makes More Sense

TensorFlow.js lets developers run machine learning models in JavaScript. The TensorFlow.js ecosystem has included face detection options and models that can run in the browser.

Choose TensorFlow.js if your app already uses it for other ML tasks.

For example:

AppWhy TensorFlow.js may fit
Browser ML dashboardOne ML runtime for several models
Custom model experimentsMore control over model pipeline
Education projectGood for learning ML in JavaScript
Research demoEasier to inspect model behavior

Compared with MediaPipe, TensorFlow.js can feel more flexible. MediaPipe usually feels more direct for production-style real-time vision tasks.

When face-api.js Is Enough

face-api.js became popular because it made face detection, landmarks, and recognition approachable in JavaScript. Many older tutorials use it.

It can still be useful for demos, prototypes, and learning projects.

Good use cases:

Use caseWhy it fits
Learning face detectionMany examples exist
Quick prototypeSimple API style
Small internal demoGood enough for tests

Before using it in a production app, check current maintenance, model quality, browser performance, and security expectations. For a new app in 2026, MediaPipe is usually the stronger first test.

What About the Native FaceDetector API?

Some browsers have worked on a native FaceDetector API as part of the Shape Detection API. MDN’s FaceDetector page notes that browser support is limited.

A native API can be nice because you do not need to ship your own model files. The problem is cross-browser support. If your users are on different browsers and devices, test carefully before relying on it.

Native face detection can fit:

Use caseFit
Browser experimentGood
Chrome-only internal toolPossible
Public production appRisky
Cross-browser appUse MediaPipe instead

When a Server-Side API Makes Sense

Client-side detection is great for speed and privacy. Server-side processing can still make sense for some workflows.

Use a backend API when:

NeedWhy server-side helps
Uploaded video filesProcess after upload
Compliance loggingCentralized records
Large batch jobsEasier to run in backend queue
Multiple AI stepsCombine face detection, OCR, transcription, moderation
Team dashboardsStore results in a database

The tradeoff is latency and privacy. Sending video frames to a server means you must think about storage, retention, consent, and security.

A server workflow may look like this:

User uploads video → Backend stores file → Worker extracts frames → Face detector runs on selected frames → Results are saved as timestamps and boxes → Dashboard shows face count and time ranges

For live camera features, browser-side detection is usually better. For archive processing and reporting, backend processing can be easier to manage.

Who Benefits from Face Detection in Video?

Businesses

Businesses can use face detection to improve video workflows without manually reviewing every frame.

Business use caseExample
Video quality checksConfirm a speaker appears in frame
Meeting toolsCenter the active speaker
E-learningCheck whether a presenter is visible
Retail analyticsCount visible faces in public-facing media with consent
Media librariesTag video segments that contain people
Creator platformsAdd auto-crop or face-aware thumbnails

Businesses should keep the use case narrow. Face detection is most useful when it improves a clear workflow: framing, tagging, review, accessibility, or editing.

Developers

Developers benefit because face detection can run directly in the browser.

That means:

Developer benefitWhy it helps
Lower server costNo need to upload every frame
Lower latencyDetection happens on-device
Better privacy designRaw camera feed can stay local
Easier UI effectsCanvas overlays update in real time
Faster prototypesOne HTML page can prove the concept

For production, developers should optimize frame rate, memory usage, and model loading. A detector that works on a laptop may run slowly on low-end phones.

Product Teams

Product teams can use face detection for features users actually notice.

Examples:

FeatureUser benefit
Auto-framingKeeps the person centered
Blur background triggerApplies effect when a face is found
Face-aware croppingBetter thumbnails
Video recording checksWarns if no face is visible
Creator filtersAdds effects in the right location

The product question is not “can we detect a face?” The useful question is “what better experience does detection create?”

Creators and Media Teams

Creators can use face detection for editing and automation.

Examples:

WorkflowHow face detection helps
Shorts creationFind segments with a speaker on screen
Thumbnail generationPick frames with clear faces
Video cleanupFlag shots where the subject is missing
Auto-croppingKeep faces inside vertical video
EffectsAttach overlays to face position

This is where browser tools can be very useful. A creator app can preview effects live without waiting for backend processing.

Privacy and Safety Notes

Face detection touches sensitive data because it uses camera video and images of people.

Use these rules:

RuleWhy
Ask for camera permission clearlyUsers should know what happens
Process locally when possibleReduces data exposure
Avoid storing raw video unless neededLowers privacy risk
Explain what is detectedFace location, count, or landmarks
Do not identify people unless requiredRecognition has higher risk
Add opt-out controlsImportant for trust
Review laws for your marketBiometrics rules vary by region

For browser apps, a strong privacy pattern is:

Camera opens locally → Face detection runs in browser → Only box coordinates or counts are used → No raw frames are uploaded

If the app sends frames or videos to a server, disclose that clearly and review retention rules.

Performance Tips

Real-time video detection can be heavy. Small changes help a lot.

TipWhy it helps
Use lower video resolutionFewer pixels to process
Process every 2nd or 3rd frameReduces CPU/GPU load
Use requestAnimationFrameSyncs with browser rendering
Prefer GPU delegate when availableFaster inference
Stop camera when doneSaves battery
Avoid drawing too muchCanvas work can become expensive
Test on mobile devicesMobile performance is different

If detection feels slow, start by lowering the camera resolution:

video: {
  width: 480,
  height: 270,
  facingMode: "user"
}

You can also skip frames:

let frameCount = 0;

function detectFaces() {
  frameCount++;

  if (frameCount % 2 === 0) {
    const result = faceDetector.detectForVideo(video, performance.now());
    drawDetections(result.detections);
  }

  requestAnimationFrame(detectFaces);
}

That cuts detection work roughly in half.

Testing Checklist

Test with real conditions, not only one perfect webcam scene.

TestWhy
Bright lightChecks normal conditions
Low lightCommon failure case
Side profileTests non-front-facing faces
GlassesCan affect detection
Hats or masksMay hide face features
Multiple peopleChecks multi-face detection
Fast movementTests frame stability
Mobile browserChecks performance
Different skin tonesHelps spot quality issues
Different camera anglesReal users move around

Face detection should be tested across devices and environments. A model can look excellent in a clean demo and still struggle in real rooms.

Where LLMAPI Can Fit

Face detection gives you visual signals. In many business workflows, those signals are only one part of the full automation.

For example:

Video upload → Face detection finds speaker timestamps → Speech-to-text creates transcript → LLMAPI summarizes key moments → Dashboard shows clips, transcript, and summary

Or:

Webcam recording → Face detection confirms person is visible → App stores metadata → LLMAPI creates a QA report from transcript and event data

LLMAPI can help when face detection connects to text, summaries, classification, moderation, or workflow routing. The face detector handles visual location. LLMAPI can help process the surrounding text and metadata.

Final Recommendation

For most JavaScript apps in 2026, start with MediaPipe Face Detector.

It is fast, modern, and suitable for real-time browser video. Use getUserMedia() to access the camera, MediaPipe to detect faces, and canvas to draw boxes.

Choose another path when the project calls for it:

NeedBest choice
Real-time browser detectionMediaPipe Face Detector
Existing TensorFlow.js appTensorFlow.js
Learning/demo projectface-api.js
Browser-native experimentFaceDetector API
Uploaded video processingServer-side API or backend model
Multi-step AI workflowFace detection + LLMAPI

Deploy in minutes