How to Test Document Scanning Apps with Custom Images Using Apple's Virtual Scanner on macOS
Apple provided a sample project demonstrating how to create a virtual scanner device a long time ago. The last revision was on June 12, 2012. In this article, we will build the sample project using the latest Xcode on macOS Sequoia and use it to test front-end document scanning applications like Image Capture and Dynamic Web TWAIN online demo.
This article is Part 3 in a 3-Part Series.
What you’ll build: A macOS virtual scanner device (built from Apple’s archived ICA sample code) that feeds custom TIFF images into any ICA-compatible scanning app — including Image Capture and Dynamic Web TWAIN — without requiring physical hardware.
Key Takeaways
- Apple’s VirtualScanner sample (last revised June 2012) compiles and runs on macOS Sequoia with a single macro fix for the deprecated Carbon
require_actionfunction. - Replacing the bundled
test.tiffwith your own image lets you feed any custom document into ICA-compatible scanning apps — eliminating the need for a physical scanner during development and QA. - The virtual scanner integrates with Dynamic Web TWAIN out of the box; however, each session supports only one scan before
_ICD_ScannerCloseDeviceterminates the device. - This workflow is the most practical approach for automated SDK integration testing and CI pipelines where scanner hardware is unavailable.
Common Developer Questions
- How do I use a virtual scanner to test document scanning apps on macOS without hardware?
- How do I fix the “Call to undeclared function ‘require_action’” build error in Apple’s VirtualScanner sample?
- Can I use Apple’s virtual scanner with Dynamic Web TWAIN or other ICA-compatible document scanning SDKs?
macOS Virtual Scanner Demo Video
Prerequisites
- Xcode
- Virtual Scanner source code provided by Apple
Step 1: Build the macOS Virtual Scanner from Source
- Unzip the sample project and open it in Xcode.
-
Build the source code. You will encounter the following error:
Call to undeclared function 'require_action'; ISO C99 and later do not support implicit function declarations
This error occurs because the
require_actionmacro is defined in the Carbon framework, which has been deprecated. To fix the issue, define the macro in bothVirtualScanner.mandEntryPoints.m:#define require_action(condition, exceptionLabel, action) \ do { \ if ( __builtin_expect(!(condition), 0) ) { \ action; \ goto exceptionLabel; \ } \ } while(0) -
The project includes a
test.tifffile as the input source. Replace it with your own image.
-
Build the project to generate VirtualScanner.app. According to Apple’s documentation, the app must be placed in the
/Library/Image Capture/Devices/directory. However, this does not work as expected. To make the virtual scanner appear in the Image Capture app, run the project directly in Xcode instead.
Step 2: Test the Virtual Scanner with Image Capture and Dynamic Web TWAIN
-
Image Capture

-

Common Issues & Edge Cases
- Single-scan session limit: The virtual scanner only supports one scan per session with Dynamic Web TWAIN. After the first acquisition,
_ICD_ScannerCloseDeviceis triggered and the device terminates. Restart the Xcode run target to reset the session. - App not appearing in Image Capture: Placing
VirtualScanner.appin/Library/Image Capture/Devices/does not work reliably on recent macOS versions. The scanner only registers correctly when launched directly from Xcode via Run. require_actioncompile error on Xcode 14+: The Carbon framework is no longer linked by default. If you seeCall to undeclared function 'require_action', add the macro definition to bothVirtualScanner.mandEntryPoints.mas shown in Step 1 above.