TechEarl

How to Take a Photo With the Mac Camera From the Command Line

Take a photo with the Mac camera from the Terminal using imagesnap: install it, list devices, pick one, add a warm-up delay, and fix the Camera-permission gap that makes a CLI capture fail silently. Plus the ffmpeg avfoundation alternative.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
Take a photo with the Mac camera from the command line using imagesnap, list and pick a device, add a warm-up delay, and grant Terminal the Camera permission so the capture does not fail silently.

To take a photo with the Mac camera from the command line, install imagesnap and run it with a filename:

bash
brew install imagesnap
imagesnap photo.jpg

That captures one frame from the default camera and writes it to photo.jpg in the current directory. If you leave the filename off, imagesnap writes to snapshot.jpg. That is the whole job for the simple case. The rest of this page is the detail that actually matters when it does not work: choosing the right camera, the warm-up delay that keeps the frame from coming out black, and the one thing that trips up everyone scripting this in 2026, the macOS Camera-permission gap that makes a CLI capture fail silently.

imagesnap is a small open-source tool by Robert Harder. It is the cleanest way to grab a still from the built-in FaceTime camera or any attached USB webcam without opening Photo Booth.

List the cameras

A Mac often has more than one capture device: the built-in camera, an attached webcam, a phone acting as a Continuity Camera. List them before you pick:

bash
imagesnap -l

That prints every video device by name. The first one in the list is the system default that a bare imagesnap photo.jpg uses.

Pick a specific camera

Pass the device name from -l with -d:

bash
imagesnap -d "FaceTime HD Camera" photo.jpg

The name has to match what -l reported. Quote it, because the names contain spaces. If you only ever use one camera you can skip this and let imagesnap take the default.

Add a warm-up delay or you get a dark frame

This is the single most common complaint, and the fix is one flag. A camera sensor needs a moment to adjust exposure after it powers on. Capture instantly and you get a dark, sometimes fully black, frame. Give it time to settle with -w:

bash
imagesnap -w 2 photo.jpg

-w 2 warms the camera up for two seconds before the shot. imagesnap already applies a default warm-up of about three seconds, so a bare imagesnap photo.jpg is usually fine, but if you have lowered it or your camera is slow to expose, bump -w until the frame is properly lit. The value is in seconds and accepts decimals (-w 1.5).

The Camera-permission gap (the real gotcha)

Here is the thing that breaks scripted captures and is absent from most older guides. Since macOS Mojave (10.14), the camera is gated behind TCC, Apple's privacy permission system. A command-line tool does not get its own permission entry. It inherits the permission of the app that launched it: the Terminal, iTerm, VS Code's integrated terminal, or whatever is running your script.

The first interactive run usually triggers a permission prompt, and clicking Allow records the grant against your terminal app. But run imagesnap from a non-interactive context (a cron job, a launchd agent, an SSH session, a CI step) before that grant exists, and there is no prompt to click. The capture fails, often quietly, and you are left staring at a missing or empty file with no obvious error.

The fix is to grant the controlling app Camera access explicitly:

  1. Open System Settings, then Privacy and Security, then Camera.
  2. Find your terminal app (Terminal, iTerm, or whichever runs your script) in the list and turn it on. If it is not listed, run imagesnap once interactively to make macOS register it, then toggle it.
  3. Quit and reopen that terminal app so the new permission takes effect.

If you script this, the rule is simple: the app that owns the process needs the grant, not imagesnap itself. Move the script to a different terminal and you need to authorize that one too.

To sanity-check whether something already holds the camera open, the green dot next to the menu bar clock lights up whenever any process is using the camera. If imagesnap returns a frame but the dot never appeared, the capture did not actually reach the sensor, which usually points back at the permission gap.

Shoot a timelapse

imagesnap can also fire on an interval instead of taking a single shot. Pass -t with the number of seconds between frames:

bash
imagesnap -t 5 frame.jpg

That captures a frame every five seconds, writing numbered files (frame00001.jpg, frame00002.jpg, and so on) until you stop it with Ctrl+C. The interval accepts decimals, so -t 0.5 gives two frames a second. To cap the run at a fixed number of shots instead of stopping by hand, add -n:

bash
imagesnap -t 5 -n 12 frame.jpg

-n 12 takes twelve frames and exits, so the command above grabs one shot every five seconds for a minute and then stops. The same Camera-permission rule below applies to a timelapse run, and a slow interval gives the sensor plenty of time to settle, so a per-frame warm-up is rarely needed here.

The ffmpeg alternative

If you already have ffmpeg installed (for transcoding or thumbnails), you can skip imagesnap entirely and capture a single frame through ffmpeg's avfoundation input:

bash
ffmpeg -f avfoundation -i "0" -frames:v 1 out.jpg

-f avfoundation selects the macOS capture backend, -i "0" is the device index (run ffmpeg -f avfoundation -list_devices true -i "" to see the numbered list), and -frames:v 1 grabs exactly one video frame. The same TCC rule applies here: the terminal running ffmpeg needs Camera permission, and avfoundation can return a dark first frame for the same warm-up reason, so add -ss 1 to seek a second in if the shot comes out underexposed.

imagesnap is the friendlier tool for a quick still. Reach for the ffmpeg form when you are already in an ffmpeg pipeline or want the frame piped straight into a larger video workflow. For the related job of pulling a still out of an existing video file rather than a live camera, see extract a thumbnail from a video with ffmpeg.

FAQ

See also

Sources

Authoritative references this article was fact-checked against.

TagsimagesnapmacOScamerawebcamCLIffmpegTerminal

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts