How to Build Angular Document Scanner with Dynamsoft Web Capture SDK

Angular Development Environment

npm install -g @angular/cli

ng --version

Angular CLI: 13.3.7
Node: 16.13.1
Package Manager: npm 8.1.2
OS: win32 x64

Angular: 13.3.10
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package Version
@angular-devkit/architect 0.1303.7
@angular-devkit/build-angular 13.3.7
@angular-devkit/core 13.3.7
@angular-devkit/schematics 13.3.7
@angular/cli 13.3.7
@schematics/angular 13.3.7
ng-packagr 13.3.1
rxjs 7.5.5
typescript 4.6.4

Creating Angular Document Scanner App Step by Step

ng new angular-document-scanner
cd angular-document-scanner
npm i mobile-web-capture
"builder": "@angular-devkit/build-angular:browser",
"options": {
"assets": [
"glob": "**/*",
"input": "./node_modules/mobile-web-capture/dist",
"output": "assets/dynamic-web-twain"
ng generate component document-scanner
  • An HTMLSelectElement for selecting the camera sources. For desktop browsers, all USB cameras are listed. For mobile browsers, all front-facing and back-facing cameras are listed.
  • A button used to trigger document scanning and a button used to download the scanned document.
  • An HTMLDivElement set as the container for storing the scanned and processed document images.
<div class="document-scanner">
<h1>Angular Document Scanner</h1>
<label for="videoSource">Video source: </label>
<select id="videoSource"></select>
<button id="scanButton" (click)="scanDocument()">Scan Document</button> <button id="scanButton" (click)="downloadDocument()">Download Document</button>

<h3>Document Container</h3>
<div id="dwtcontrolContainer"></div>

  1. Import the SDK module from mobile-web-capture package.
import Dynamsoft from 'mobile-web-capture';
import { WebTwain } from 'mobile-web-capture/dist/types/WebTwain';
dwtObject: WebTwain | undefined;
videoSelect: HTMLSelectElement | undefined;
sourceDict: any = {};

ngOnInit(): void {
this.videoSelect = document.querySelector('select#videoSource') as HTMLSelectElement;
Dynamsoft.DWT.ProductKey = "LICENSE-KEY";
Dynamsoft.DWT.ResourcesPath = 'assets/dynamic-web-twain';
Dynamsoft.DWT.Containers = [{ ContainerId: 'dwtcontrolContainer' }];
Dynamsoft.DWT.UseLocalService = false;
Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', () => { this.onReady(); });
  • Apply for a 30-day trial license and thereafter update the LICENSE-KEY.
  • Set the resource path assets/dynamic-web-twain as we configure above in angular.json file.
onReady() {
this.dwtObject = Dynamsoft.DWT.GetWebTwain('dwtcontrolContainer');

updateCameraList() {
if (this.videoSelect && this.dwtObject) {
this.videoSelect.options.length = 0;
this.dwtObject.Addon.Camera.getSourceList().then((list) => {
for (var i = 0; i < list.length; i++) {
var option = document.createElement('option');
option.text = list[i].label || list[i].deviceId;
if (list[i].label) {
this.sourceDict[list[i].label] = list[i].deviceId;
else {
this.sourceDict[list[i].deviceId] = list[i].deviceId;
if (this.videoSelect) this.videoSelect.options.add(option);

scanDocument() {
if (this.videoSelect) {
let index = this.videoSelect.selectedIndex;
if (index < 0) return;

var option = this.videoSelect.options[index];
if (this.dwtObject) {
this.dwtObject.Addon.Camera.selectSource(this.sourceDict[option.text]).then(camera => {
if (this.videoSelect) this.createCameraScanner(this.sourceDict[option.text]);



async createCameraScanner(deviceId: string): Promise<void> {
if (this.dwtObject) {
await this.dwtObject.Addon.Camera.closeVideo();
scannerViewer: {
deviceId: deviceId,
fullScreen: true,
autoDetect: {
enableAutoDetect: true
continuousScan: {
visibility: false,
enableContinuousScan: false

function () { console.log("OK"); },
function (error: any) { console.log(error.message); });

downloadDocument() {
if (this.dwtObject) {
this.dwtObject.SaveAsJPEG("document.jpg", this.dwtObject.CurrentImageIndexInBuffer);
ng serve --ssl

GitHub Page Deployment

  1. Open angular.json file to increase the size budgets. The default budgets setting may cause the error: WARNING in budgets, maximum exceeded for initial.
"budgets": [
"type": "initial",
"maximumWarning": "2.5mb",
"maximumError": "5mb"
name: Build and Deploy
- main

runs-on: ubuntu-latest

- uses: actions/checkout@v2
- name: All things angular
uses: AhsanAyaz/angular-deploy-gh-pages-actions@v1.3.2
github_access_token: $
build_configuration: production
base_href: /angular-document-scanner/
deploy_branch: gh-pages
angular_dist_build_folder: dist/angular-document-scanner

Source Code




Manager of Dynamsoft Open Source Projects | Tech Lover

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Typescript made simple

VSCode Jest Setup

DATEV Nine-Nine | Apps, libs and module-boundaries in a Nx Monorepo


Javascript is Weird

Some cool and awesome JavaScript tricks

Charts with SVGs in Angular2+

How to setup your Workflow using Gulp v4.0.0

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Xiao Ling

Xiao Ling

Manager of Dynamsoft Open Source Projects | Tech Lover

More from Medium

InboxPro | Made with Angular JS

InboxPro | Made with Angular JS

Angular 13: Custom form validator

Angular Libraries: entry-points, path mappings and workspace configurations

How to Build a Responsive Dashboard Application in Angular — Part 2