Unify Logo Footer.svg
Unify Applications
Logo
Camera, Scanner & Barcode

Camera, Scanner & Barcode

Logo

11 mins READ

Camera, Scanner & Barcode

Capture photos and video, scan barcodes and QR codes through the camera, or render scannable barcodes from your data.

Choosing the Right Block

BlockPurposePlatform
CameraLive feed photo capture and video recording. Supports Face Detection (web) and Recording add-ons.Web + Native mobile
Photo BoothRicher mobile capture experience with crop, drawing, flash, and gallery. Designed for native mobile apps.Native mobile only
ScannerDecode barcodes and QR codes from the camera feed. Accumulates decoded values in a data array.Web + Native mobile
BarcodeRender a scannable barcode graphic from a text value. Display-only — no camera, no scanning.Web + Native mobile
File UploadPick existing files from the device (no camera). See the File Upload page.Web + Native mobile

Camera Block

The Camera block shows a live camera feed and captures photos or records video clips. Captured photos are uploaded automatically and exposed as a file object. Two add-ons extend its capabilities: Recording for video, and Face Detection (web only) to gate the shutter until a face is properly framed.

Content properties

PropertyTypeDefaultDescription
facingMode"user" | "environment"user (Front)Which camera the feed starts on. Front for selfies; back (environment) for document or environment capture.
mirrorbooleantrueWhether the preview is flipped horizontally (selfie-style). Does not affect the captured image.
showImagePreviewbooleanShows a preview page after capture with edit options. Mobile apps only.

Add-ons

Add-onPlatformKey settings
Face DetectionWeb onlyOrientation (portrait/landscape) and Detect Face toggle. When enabled, the shutter is hidden until a face is detected, centered, and aligned — live guidance messages coach the user. Any Recording settings disable Face Detection.
RecordingWeb + MobileAuto Record (start on open, once), Include Audio, Duration (ms), FPS, Loop (restart after each clip), Loop Iterations. Enables video output instead of photo capture.

Appearance properties (mobile only)

PropertyDefaultDescription
showTorchButtonfalseShows a torch on/off button.
showSwitchCameraButtonfalseShows a front/back switch button.
showGalleryButtonfalseLets the user pick from the device gallery instead of capturing.

Events

EventWhen it fires
On Photo CaptureAfter a captured photo finishes uploading. The file is in {{ id.uploadedImage }}. Does not fire if upload fails.
On Recording StartWhen recording begins (manual, auto, or via method).
On Recording StopWhen recording ends.
On Recorded File CaptureAfter a finished clip is saved and uploaded.
On Permission DeniedWhen the user denies camera access.
On Face DetectedWhen Face Detection reports a face (Face Detection add-on only).

Methods

MethodDescription
switchCameraSwitches between front and back cameras. Ignores the facingMode parameter — always toggles to the other camera.
startRecordingStarts a recording.
stopRecordingStops the current recording.

Exposed state

Key ({{ id.* }})TypeDescription
previewImagestringLast captured image as inline data — available immediately at capture time.
uploadedImageobjectUploaded photo file details (name, url, type). Set only after upload completes.
isCameraRecordingbooleanWhether a recording is in progress.
recordedVideoFileobjectThe last finished video clip. Holds only the most recent clip in a loop — save each one in On Recorded File Capture.
hasCameraPermissionbooleanWhether the user has granted camera access. Starts true; flips to false on denial.
hasGalleryPermissionbooleanWhether gallery access is granted (mobile).

Warning: On Photo Capture fires after upload, not at the shutter. {{ id.previewImage }} is set immediately when the photo is taken. {{ id.uploadedImage }} and the event fire only after upload completes. On slow connections there is a visible gap. Gate downstream actions on the event, not on button click.

Note: Auto Record runs once per page visit. With Auto Record on, recording starts automatically once the camera opens — but only once. After the first clip completes it will not auto-start again. Use startRecording to capture another take, or enable Loop with Loop Iterations.

Photo Booth Block

The Photo Booth block is a richer capture surface designed for native mobile apps. It supports photo and video modes together, crop and annotation add-ons, quality presets, gallery picking, flash, and camera switching. It is not available in web apps.

Content properties

PropertyTypeDefaultDescription
facingMode"user" | "environment"user (Front)Which camera opens first.
quality"4k" | "fhd" | "hd"4kCapture resolution.
aspectRatio"1_1" | "4_3" | "16_9" | "FULL_SCREEN"4_3Frame shape of the capture.
photoModebooleantrueEnables photo capture. Add-ons for crop, drawing, and flash only appear when this is on.
mirrorbooleanfalse (true on new block)Flips the captured photo horizontally (selfie-style). Photo mode only.
videoModebooleanfalseEnables video recording. When on, exposes: Recording Method (tap/hold), FPS (30/60), Max Duration (ms).

Add-ons

Available from Inspector → Content → Add-ons. View Gallery and Switch Camera are always offered. Photo Crop, Drawing Support, and Flash Light appear only when Photo Mode is on.

Events

EventWhen it fires
On Photo CaptureAfter a photo finishes uploading (after any crop/draw step). Cancelling crop or drawing discards the capture and fires nothing.
On Recording Start / StopWraps the recording itself. Use Stop for UI feedback.
On Recorded File CaptureAfter the video uploads. Use this event to act on the video — it fires separately from On Recording Stop.
On Permission DeniedDeclared but does not fire in the native runtime — watch {{ id.hasCameraPermission }} instead.

Exposed state

Key ({{ id.* }})Description
previewMediaLocal preview of the latest capture (image or video frame), set at capture time.
uploadedMediaUploaded file details (URL, name, type). Set once upload completes.
isCameraRecordingWhether a recording is in progress.
hasCameraPermissionWhether camera access is granted.
hasGalleryPermissionWhether gallery access is granted.

Scanner Block

The Scanner block opens a live camera feed with a framed scan region and decodes barcodes and QR codes as they enter the frame. Each accepted read appends to the block's data array and fires On Scan. Duplicates are skipped by default. The block can operate in continuous mode (keeps scanning) or single-shot mode (pauses on first hit).

Content properties

PropertyTypeDefaultDescription
defaultCamera"user" | "environment"environment (Back)Which camera the feed opens with. Back camera is typical for scanning physical items.
scanCodeTypeBARCODE | QR_CODE | BOTHBOTHWhich code family to decode. Codes in unsupported formats are silently ignored.
pauseAfterScanbooleanfalseFreeze on the first successful read (single-shot). Call Resume to read the next item. Mutually exclusive with timeBetweenScans.
ignoreDuplicateCodesbooleantrueSkip a code already present anywhere in the data array. Skipped duplicates do not fire On Scan.
timeBetweenScansnumber (ms)800Delay the scanner waits after a read before accepting the next one. Applies only in continuous mode (pauseAfterScan off).

Scan region appearance

The framed target area is configured under Appearance → Scan Region. Width and height default to 336×336 px. Frame corner brackets (Color, Radius, Gap) and the animated scan line (Line Color) are independently styled. For a gradient scan line, supply a lineStyles.linearGradient object via Custom CSS.

Events, Methods & State

NameTypeDescription
On ScaneventFires once per accepted read after the value is stored. No payload — read the value from {{ id.data }} (last element is the newest).
PausemethodFreezes scanning with a paused overlay. The feed stays live but no reads are accepted.
ResumemethodResumes scanning after a pause or after pauseAfterScan hit.
ClearmethodEmpties the data array. Does not pause or affect the camera feed.
{{ id.data }}string[]Every accepted scan value in order. Starts empty on mount; only the Clear method empties it. No way to seed or override from outside.

Platform differences

Web supports: Code 128, Code 39, EAN-13, EAN-8, UPC-A, UPC-E, ITF, Code 93, Codabar, and QR. Mobile apps support: EAN-13, EAN-8, Code 128, Code 39, Code 93, Codabar, and QR — but not UPC-A, UPC-E, or ITF. Test your specific symbology on the platforms you ship to. A code in an unsupported format is silently ignored.

Warning: Duplicate checking spans the full history. With Ignore Duplicate Codes on, a value already anywhere in data is not added again — even if the user genuinely rescans the same item later. To allow re-scanning the same code, either turn the setting off or call Clear between sessions.

Barcode Block

The Barcode block renders a scannable one-dimensional barcode from a text value. It is a display block only — no camera, no events, no methods. Dropping it creates a stack: the barcode graphic plus a separate caption text block underneath, both prefilled with a sample value.

Properties

PropertyTypeDefaultDescription
textstringUnifyAppsThe value encoded into the bars. Bindable. An empty value renders nothing. An invalid value for the selected format renders nothing and logs an error silently.
typeformat enumCODE128Barcode format: CODE128, CODE128A/B/C, EAN13, EAN8, UPC, CODE39, ITF14, ITF, MSI, MSI10, MSI11, MSI1010, MSI1110, pharmacode. Each format has its own character and length rules.
barWidthpixels2pxWidth of the thinnest bar.
colors.barColorcolornear-blackColor of the bars. Accepts conditional expressions.
colors.backgroundColorcolortransparentBackground behind the bars.

Warning: The caption under the bars is a separate block. Changing the barcode's Text does not update the caption text block — they are independent. Bind or edit the caption block separately, or the label and the bars will say different things.

Exposed state

{{ id.content.text }} (string) — the encoded value. {{ id.content.type }} (string) — the selected format. No events or methods.

Common Gotchas

Photo Booth is native mobile only

The Photo Booth block is not available in web apps. It does not appear in the web block library and a page using it has no web fallback. For web photo capture, use the Camera block instead.

switchCamera always toggles — it ignores the facingMode parameter

Both Camera and Photo Booth expose a switchCamera method that takes a facingMode parameter in its UI, but both blocks ignore the parameter and simply toggle to whichever camera is not currently active. Call it twice and you're back where you started.

Face detection and recording are mutually exclusive on Camera

If the Recording add-on has Auto Record, Duration, Loop, or Loop Iterations set, face detection stops working even when its toggle is on. Recording wins. Choose one capability per Camera block.

On Photo Capture fires after upload, not at the shutter press

For both Camera and Photo Booth, the event fires after the upload completes, not when the shutter is pressed. previewImage / previewMedia updates immediately at capture time, but use the event and the uploadedImage / uploadedMedia state for anything that needs the real backend URL.

Barcode renders nothing for invalid or empty text

If the Text doesn't satisfy the selected format's rules — for example letters in an EAN13 that needs only digits — no error is shown. The block keeps displaying whatever it last rendered successfully, or stays blank. Validate bound values upstream when the format is strict.

On Permission Denied does not fire in the Photo Booth native runtime

A camera-permission refusal updates hasCameraPermission to false and shows an access-denied panel, but the On Permission Denied event handler is not invoked on native. Watch {{ id.hasCameraPermission }} instead of relying on the event for Photo Booth on mobile.

Frequently Asked Questions

Can I use the Camera block to scan barcodes?

The Camera block is designed for photo and video capture — it does not decode barcodes or QR codes. Use the Scanner block for barcode and QR code reading. The Scanner and Camera blocks share camera hardware but serve entirely different purposes.

How do I save each photo from a looped recording session?

When the Camera block is set up with Loop, each completed clip fires On Recorded File Capture. At that point {{ id.recordedVideoFile }} holds the just-finished clip. Wire that event to a "save file to record" action — each iteration fires separately, so your action runs once per clip. If you need all clips together, push each recordedVideoFile into a page variable array from within the event handler.

Why does my Scanner not detect a barcode that I can scan with a phone camera?

The Scanner block only decodes formats in its supported list, which differs between web and native. On mobile, UPC-A, UPC-E, and ITF formats are not supported — codes in those formats are silently ignored. Verify the barcode's format against the platform's supported list. Also confirm the code falls clearly within the framed scan region; codes outside the region are not read.

Can I pre-fill the Barcode block with data from my database?

Yes. Bind the Text property to any expression — a table row's ID, a query result field, a variable. The barcode re-renders reactively whenever the bound value changes. Just make sure the bound value satisfies the selected format's character and length rules; invalid values render nothing silently.

When should I use Photo Booth vs. Camera block on a mobile app?

Use Photo Booth when you need crop, annotation/drawing, flash control, or gallery picking as part of the capture flow — it provides a full guided capture UI. Use Camera when you need programmatic control (Face Detection, auto-record, recording loops, method-triggered capture) or when you are building for both web and mobile with one shared block. Camera is the more flexible; Photo Booth is the richer out-of-the-box mobile experience.

Step-by-Step Examples