iOS Simulator · Free
A working camera in the iOS Simulator
Updated August 2026
Pick what the camera should show. That is the whole setup.
Open Buoy Desktop, choose Simulator Camera, and click a source. That click turns the camera on for that simulator — so anything it launches afterwards has one, whether you start your app with npx expo start, react-native run-ios, Xcode or a test runner. Then run your app the way you always do.
There is no second confirm step and no launcher to choose. The panel then answers the only question worth asking — “Your app is receiving it” — so you are never left guessing whether it worked or whether you are staring at a camera pointed at something dark.
One caveat, and it is a property of the platform rather than of Buoy: a camera is attached when a process starts. An app that is already running will not suddenly have one, and a Fast Refresh reload is not enough — the process has to be new. Changing the source afterwards is instant and needs no relaunch at all.
Six things it can be
A region of your Mac screen
Drag a rectangle onto anything on your desktop — a QR code in your browser, a photo of a licence, an invoice in Preview — and that is what the phone’s camera sees. Resize it from its handles, move it, and the framing follows on the next frame.
A webcam
Your Mac camera, straight through. The right one for testing a selfie flow, face detection or anything that needs a real moving human in frame.
A generated barcode
Type a payload, pick QR, PDF417, Aztec or Code 128, and it is on the camera a moment later. Swap the text to test the next case — no printing, no finding a fixture.
An image
Any file on disk, held steady in frame. Fixtures that never drift, which is what makes a scanner test repeatable.
A video
A recorded clip on loop, for flows that need motion rather than a still.
A test pattern
A generated pattern, for proving the pipeline works before you blame your own code.
Point the phone at your own screen
This is the part that has no equivalent on a real device. Choose the screen source and your own Mac becomes the viewfinder: point it at a QR code on a web page, a driver's licence in Preview, a boarding pass in your email — and your app scans it. No printing, no second device, no holding a phone up to a webcam.
You aim it with a region: a dashed rectangle you drop anywhere on your desktop, above every window, with eight handles to resize it — the same gesture as a Mac screenshot, except it stays there and streams. Drag its middle to move it, press Escape to dismiss it. Turn on click-through and you can keep scrolling the page it is pointed at while it films.
Resizing snaps to 16:9, because that is the only shape the camera has — the fabricated device advertises a single 1280×720 format, so a region of any other shape arrives centred inside a 16:9 frame with black bars. Hold Shift while resizing for a free-form region anyway.
That rectangle is the only screen target the panel offers, on purpose: aiming at a whole display or a named window meant the camera was rarely looking at the thing you actually wanted. The CLI still takes them — behind, display and window:<id> — for CI, where nobody is there to drag anything.
Buoy's own windows and the Simulator are excluded from the capture. That is not cosmetic: include the Simulator and it films itself, include Buoy and the live preview appears inside the frame it is previewing. Either one is an infinite mirror. It is also what keeps the region's dashed border and handles out of the shot.
Barcodes, not just QR
Anything read through AVCaptureMetadataOutput works: QR, PDF417 — the barcode on the back of a US driver's licence — Aztec, DataMatrix, EAN-8/13, UPC-E, Code 128, Code 39, Code 93 and ITF. Your onBarcodeScanned fires exactly as it would on a device.
Detection runs on your Mac rather than inside your app, and that is a deliberate consequence of a real limitation: Vision's barcode detector cannot create an inference context inside the iOS Simulator, so an in-process decoder could only ever manage QR. Doing it host-side gets the whole family and keeps the per-frame cost out of your app's process entirely.
Nothing goes into your app
This is the one Buoy tool with no npm package. There is no provider to mount, no config plugin, no prebuild — and it works on any booted simulator app, including apps that have never heard of Buoy. You can point it at a build from another team, or at a release binary, and it still has a camera.
Buoy loads a small library into the simulator at launch. It fabricates two capture devices and implements enough of the AVFoundation capture graph that real camera libraries build a session around them; a helper on your Mac captures the source you picked and publishes frames into shared memory. Because the fabrication happens at the system framework level, what you build on top of it does not matter — React Native, Flutter, UIKit or SwiftUI all go through the same API.
What has actually been verified
Framework-level fabrication means most things are expected to work. This table lists only what has actually been run, because expected and tested are not the same claim:
| Library | Verified | What was exercised |
|---|---|---|
expo-camera | Yes | Preview, takePictureAsync, barcode scanning |
react-native-vision-camera | Yes | Device list, preview, its hand-built capture graph (v5) |
AVCaptureSession | Yes | UIKit and SwiftUI — exercised by the test suite on every run |
camera | Yes | Flutter's plugin — preview, frame stream, photo capture, video recording |
| WebRTC / Agora | No | Not attempted. Both need live infrastructure to test honestly |
Libraries that refuse to look
A few camera libraries decide at compile time that a simulator has no camera, so they never ask for one — a fabricated device is invisible to them however well it works. buoycam patch finds them and, where the fix is purely mechanical, applies it:
buoycam patch # what is installed, and what is affected
buoycam patch apply # fix what can be fixed safelyexpo-camera was fixed upstream in 55.0.11 and react-native-vision-camera in 5.0, so for those the answer is usually just to upgrade. Only the mechanical case is rewritten automatically, only when the guard matches exactly, and the original is kept alongside — where upstream restructured the file, Buoy says so and points at the release instead of improvising inside your node_modules.
For terminals, CI and coding agents
Everything the panel does is also a command, with --json on all of it:
buoycam source barcode "hello" # or: camera, image, video, screen, pattern
buoycam source barcode "DL@ANSI…" --format pdf417
buoycam codes # what it is decoding right now
buoycam diagnose # why isn't this workingdiagnose exists because “it is not working” has several very different causes, and it names which one: nothing is publishing, something is publishing but your app is not reading it, the library never loaded into that process, or another tool has claimed the simulator. It exits non-zero when something is broken, so it works as a CI gate rather than as something to read.
In CI there is no licence to activate and no token to store. The generated barcode, image, video and test-pattern sources all work without a logged-in desktop session; the webcam and screen sources do not, because both need a real session and a permission a headless runner cannot grant. For scanner tests — which is most of what CI wants a camera for — the generated barcode source is the right one anyway.
Buoy's MCP server exposes the same four actions, so an agent can set up a scanner test without being told how: camera_source, camera_status, camera_launch and camera_diagnose.
Limits, stated plainly
- iOS Simulator only. Not physical devices — an app's camera access there is outside any debugging tool's reach. The Android emulator already supports webcams natively.
- No video recording.
AVCaptureMovieFileOutputis not implemented; preview and still capture are. - Front and back cameras show the same feed.
- GS1 DataBar and the Micro symbologies are not mapped, though the rest of the family is.
- Only one tool can own the simulator's injection at a time. If another simulator-camera app is running, quit it first.
Can the iOS Simulator use a camera?
Can I scan a QR code or a driver’s licence in the Simulator?
Do I have to install anything in my app?
Does it work with expo-camera and react-native-vision-camera?
Does it work in CI?
Is it free?
Give your Simulator a camera
No package, no config plugin, nothing in your app. Free on any booted simulator app; Pro adds the screen region, ID barcodes and agent control.
buoycam source barcode "hello"