How to Build Angular Document Scanner with Dynamsoft Web Capture SDK

Dynamsoft Web Capture SDK is a camera-based document scanning SDK implemented in WebAssembly and JavaScript. Comparing to Dynamic Web TWAIN, the classic web scanner SDK, there is no local service installation required, which means the web capture SDK can work in any desktop browser, mobile browser, and WebView. This article guides you through how to build an Angular document scanner app using the web capture SDK from scratch.

Angular Development Environment

  • Node.js
  • Angular CLI v13.3.7

      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
  • Dynamsoft Web Capture SDK v17.2.5

Creating Angular Document Scanner App Step by Step

We scaffold a new Angular project via ng new command and install Dynamsoft Web Capture SDK in terminal:

ng new angular-document-scanner
cd angular-document-scanner
npm i mobile-web-capture

Then open the angular.json file to configure the assets.

  "builder": "@angular-devkit/build-angular:browser",
  "options": {
    "assets": [
        "glob": "**/*",
        "input": "./node_modules/mobile-web-capture/dist",
        "output": "assets/dynamic-web-twain"

When running ng build, all static resource files will be copied to the assets/dynamic-web-twain folder.

The next step is to create a document scanner component, which contains document-scanner.component.css, document-scanner.component.html, document-scanner.component.spec.ts, and document-scanner.component.ts files.

ng generate component document-scanner

The target UI layout includes following elements:

  • 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.

The UI implementation in document-scanner.component.html is as follows:

<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>


Now, we are going to add the corresponding TypeScript code in document-scanner.component.ts.

  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';  
  2. In ngOnInit(), initialize the SDK.

     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(); });

    Two things need to be noted here:

    • 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.
  3. Once the OnWebTwainReady event is triggered, we get the SDK instance and update the camera source list.

     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);
  4. Select a camera source and start document scanning.

     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); });
  5. After capturing and editing a document image, we can save it to local disk.

     downloadDocument() {
       if (this.dwtObject) {
         this.dwtObject.SaveAsJPEG("document.jpg", this.dwtObject.CurrentImageIndexInBuffer);
  6. Run the Angular document scanner in desktop and mobile browsers:

     ng serve --ssl

    Desktop browser

    Angular document scanner for desktop browser

    Mobile browser

    Angular document scanner for mobile browser

GitHub Page Deployment

One more thing is to deploy the Angular document scanner project to GitHub pages.

Here are the steps:

  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"
  2. Create a GitHub action workflow:

     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

    You need to replace angular-document-scanner with your project name.

  3. After the build is done, go to your GitHub Settings > Pages to launch the GtiHub page with the gh-pages branch. Don’t forget to check the Enforce HTTPS option.

Try the Demo Page

Source Code