How to Digitize Paper Documents in Angular Web Applications

In a world that is increasingly digital, the ability to transform physical paper documents into electronic files by scanning them from a multi-function printer (MFP) has become a fundamental requirement for businesses of all sizes. Scanning paper documents helps create a more organized and efficient workspace. E-documents foster better collaboration between employees and departments in an organization. Dynamic Web TWAIN was born to help developers build web-based document scanning applications. Since from version 18.0, Dynamic Web TWAIN released a new feature called Remote Scan that allows users to wirelessly scan paper documents from a web browser on any device. In this article, we will dive into the Remote Scan feature by building a web application with Angular.

What is Dynamic Web TWAIN Remote Scan?

Dynamic Web TWAIN is designed using the C/S (Client/Server) model. The SDK package comprises two parts: a client-side JavaScript library and a Dynamsoft service that includes a built-in web server and scanner access modules. The client-side library communicates with the Dynamsoft service via the HTTP/HTTPS protocol.

Before version 18.0, the Dynamsoft service was only accessible from the host machine itself via localhost or When you open a web page integrated with Dynamic Web TWAIN, you must install the Dynamsoft service the first time.

install Dynamsoft service

The Remote Scan removes the restriction of accessing Dynamsoft service solely from the host machine. It exposes Dynamsoft service via a public IP address or domain name using Bonjour. Additionally, it provides a proxy service, built with Bonjour technology, to help you discover all Dynamsoft services running on the local network.

Dynamic Web TWAIN remote scan

Why is Remote Scan Superior to Local Host Scan?

  • You don’t need to install the Dynamsoft service on every host machine. A single PC can transform all TWAIN scanners on the local network into web scanners.
  • You can easily scan paper documents to Windows, Linux, macOS, Android, iOS, Chrome OS, and Raspberry Pi without concerns about MFP driver compatibility.

Try Online Demo


Setting Up Dynamsoft Service and Proxy in Windows

Making host machines discoverable via Bonjour

  1. Install Dynamsoft service on every host machine that has a TWAIN scanner connected.

  2. Open in your web browser to enable the host machine to be accessed from the local network. By default, the network access is disabled.

    Dynamsoft service

Configuring the proxy service

  1. Install the proxy service package as an administrator on a host machine. The proxy service manages data transmission between the client-side library and the Dynamsoft service, functioning similarly to a router. If deployed on a powerful server, a single proxy service can serve hundreds of users simultaneously. The proxy service can also be installed on cost-effective hardware like the Raspberry Pi. You can start with one Raspberry Pi and add more devices to manage traffic as scaling needs arise.

  2. Visit to enable the proxy service.

    Dynamsoft proxy service

  3. Open to bind your IP address to a custom domain. The domain name is used to access the proxy service from the client-side library. The certificate is used for HTTPS communication between the client-side library and the proxy service.

    bind domain

  4. Upload the certificate and then click the Update button to activate the proxy service.

    proxy setup succeeded

Quick Start an Angular Application for Document Scanning

  1. Install the Visual Studio extension Angular Snippets for Dynamic Web TWAIN.
  2. Press Ctrl+Shift+P to open the command palette and then select DWT: Create Angular Application to create an Angular application with Dynamic Web TWAIN.

    create angular application

  3. Request a 30-day FREE trial license and update the license key in src/app/dynamic-web-twain.service.ts:

     Dynamsoft.DWT.ProductKey = "LICENSE-KEY";
  4. Run npm install && ng serve --ssl to start the application.

    angular application with dwt

Create an Angular Component to Support Remote Scan

Create a new Angular component named remote-scan:

ng generate component remote-scan

Open remote-scan.component.html to add the following HTML code:

<div class="row">
    <label for="BW">
        <input type="radio" value="0" name="PixelType">B&amp;W </label>
    <label for="Gray">
        <input type="radio" value="1" name="PixelType">Gray</label>
    <label for="RGB">
        <input type="radio" value="2" name="PixelType" checked="checked">Color</label>

    <select (change)="onServiceChange($event)">
        <option *ngFor="let option of serviceOptions" [value]="option.value"></option>

<div>Source: <select id="sources"></select></div>
<button (click)="acquireImage()">Scan Documents</button>

<div id="dwtcontrolContainer"></div>

<div class="row">
    <label style="font-size: x-large;">
        <input type="radio" value="jpg" name="ImageType" id="imgTypejpeg" />JPEG</label>
    <label style="font-size: x-large;">
        <input type="radio" value="tif" name="ImageType" id="imgTypetiff" />TIFF</label>
    <label style="font-size: x-large;">
        <input type="radio" value="pdf" name="ImageType" id="imgTypepdf" checked="checked" />PDF</label>
<button (click)="downloadDocument()">Download Documents</button>

Compared to local host scanning, which only lists connected devices, an additional <select> element is added to allow users to choose the Dynamsoft service first. Once the service is selected, the <select> element for TWAIN sources will update accordingly.

Now, open remote-scan.component.ts to add TypeScript code.

  1. Import the relevant modules:

     import { Component, OnInit } from '@angular/core';
     import Dynamsoft from 'dwt';
     import { RemoteScanObject } from 'dwt/dist/types/RemoteScan';
     import { ServiceInfo, Device, DeviceConfiguration } from 'dwt/dist/types/WebTwain.Acquire';
     import { DynamicWebTWAINService } from '../dynamic-web-twain.service';
  2. Initialize a remote scanning object with an HTTP/HTTPS address:

     ngOnInit(): void {
     async onReady(): Promise<void> {
       var serverurl = "";
       if (window.location.protocol === 'https:') {
         serverurl = "";
       this.dwtObject = await Dynamsoft.DWT.CreateRemoteScanObjectAsync(serverurl);
       this.container = document.getElementById("dwtcontrolContainer") as HTMLElement; = 600 + "px"; = 600 + "px";
       let ret = this.dwtObject.Viewer.bind(this.container);
       ret =;

    You can also change the serverurl to, a public service provided by Dynamsoft. This is intended solely for testing purposes and should not be used in production.

  3. Find all services and relevant devices: = await this.dwtObject.getDynamsoftService();
     if ( {
       if ( > 0) {
         this.serviceOptions.splice(0, 1);
       for (let i = 0; i <; i++) {
         let service =[i];
         if ( > 0) {
           this.serviceOptions.push({ label:, value: service.attrs.UUID });
         else {
           this.serviceOptions.push({ label: service.attrs.UUID, value: service.attrs.UUID });
     async findSources(service: ServiceInfo): Promise<void> {
       var devicetype =
         Dynamsoft.DWT.EnumDWT_DeviceType.TWAINSCANNER |
         Dynamsoft.DWT.EnumDWT_DeviceType.WIASCANNER |
         Dynamsoft.DWT.EnumDWT_DeviceType.TWAINX64SCANNER |
         Dynamsoft.DWT.EnumDWT_DeviceType.ICASCANNER |
         Dynamsoft.DWT.EnumDWT_DeviceType.SANESCANNER |
         Dynamsoft.DWT.EnumDWT_DeviceType.ESCLSCANNER |
       this.devices = await this.dwtObject!.getDevices({
         serviceInfo: service,
         deviceType: devicetype,
       if (this.devices) {
         this.selectSources = <HTMLSelectElement>document.getElementById("sources");
         this.selectSources.options.length = 0;
         for (let i = 0; i < this.devices.length; i++) {
           this.selectSources.options.add(new Option(this.devices[i].name, i.toString()));
  4. Acquire paper documents from scanners and save them as JPEG, TIFF or PDF:

     acquireImage(): void {
       if (!this.dwtObject)
       let pixelType = '2';
       var pixelTypeInputs = document.getElementsByName("PixelType");
       for (var i = 0; i < pixelTypeInputs.length; i++) {
         if ((<HTMLInputElement>pixelTypeInputs[i]).checked) {
           pixelType = (<HTMLSelectElement>pixelTypeInputs[i]).value;
       let type = Dynamsoft.DWT.EnumDWT_PixelType.TWPT_RGB;
       if (pixelType === '0') {
         type = Dynamsoft.DWT.EnumDWT_PixelType.TWPT_BW;
       else if (pixelType === '1') {
         type = Dynamsoft.DWT.EnumDWT_PixelType.TWPT_GRAY;
       let config : DeviceConfiguration = {
         PixelType: type,
       this.dwtObject.acquireImage(this.devices![this.selectSources!.selectedIndex], config);
     downloadDocument() {
       if (this.dwtObject && this.dwtObject.howManyImagesInBuffer > 0) {
         if ((<HTMLInputElement>document.getElementById("imgTypejpeg")).checked == true) {
           this.dwtObject.saveImages('DynamicWebTWAIN.pdf', [this.dwtObject!.currentImageIndexInBuffer], Dynamsoft.DWT.EnumDWT_ImageType.IT_JPG);
         else if ((<HTMLInputElement>document.getElementById("imgTypetiff")).checked == true) {
           let indexes = Array.from({ length: this.dwtObject.howManyImagesInBuffer }, (_, index) => index);
           this.dwtObject.saveImages('DynamicWebTWAIN.pdf', indexes, Dynamsoft.DWT.EnumDWT_ImageType.IT_TIF);
         else if ((<HTMLInputElement>document.getElementById("imgTypepdf")).checked == true) {
           let indexes = Array.from({ length: this.dwtObject.howManyImagesInBuffer }, (_, index) => index);
           this.dwtObject.saveImages('DynamicWebTWAIN.pdf', indexes, Dynamsoft.DWT.EnumDWT_ImageType.IT_PDF);

Test the Angular Application for Document Scanning

npm install 
ng server --ssl

angular web paper document scan

Source Code