How to Read 1D/2D Barcodes from Multi-Page PDFs in Node.js

You can decode 1D and 2D barcodes from a multi-page PDF in Node.js with the dynamsoft-capture-vision-for-node package: one CaptureVisionRouter.captureMultiPagesAsync() call returns one result per page, and each result’s originalImageTag.pageNumber tells you which page every barcode came from. This saves you from manually rasterizing PDF pages or iterating page by page — the SDK handles the whole document in a single worker-thread call and runs on Windows, Linux, and macOS.

What you’ll build: A CLI barcode reader for multi-page PDFs built with Dynamsoft Capture Vision. npm install + node index.js barcodes.pdf prints every decoded barcode — format, text, confidence, and location — grouped by page, and the bundled test PDF (barcodes.pdf) contains 17 barcodes across 12 formats for immediate verification. The sample also supports exporting all results to a JSON file and swapping preset templates for speed- or read-rate-first decoding.

Key Takeaways

  • CaptureVisionRouter.captureMultiPagesAsync(pdfPath, EnumPresetTemplate.PT_READ_BARCODES) decodes every page of a PDF and returns one CapturedResult per page — no page splitting, FileFetcher, or result listener is required.
  • Each page result’s originalImageTag exposes pageNumber and totalPages; barcodeResultItems lists the decoded barcodes for that page with formatString, text, confidence, angle, and a four-point location.
  • The bundled barcodes.pdf test file contains 5 pages with 17 barcodes across 12 formats (QR Code, Code 128, EAN-13, DataMatrix, PDF417, UPC-A, UPC-E, EAN-8, Code 39, Code 93, ITF, and Codabar).
  • The reader is a single index.js file with no native build step: dynamsoft-capture-vision-for-node ships precompiled binaries for Windows (x86/x64), Linux (x64/arm64), and macOS (x64/arm64), so npm install is all you need.
  • CaptureVisionRouter.terminateIdleWorkers() must be called at the end so the SDK’s worker pool does not keep the Node.js process alive.

Common Developer Questions

How do you read barcodes from a multi-page PDF in Node.js?

Install dynamsoft-capture-vision-for-node, call LicenseManager.initLicense() with a Dynamsoft Capture Vision license, then call CaptureVisionRouter.captureMultiPagesAsync(pdfPath, EnumPresetTemplate.PT_READ_BARCODES). The Promise resolves to an array with one CapturedResult per page; each result contains barcodeResultItems for the decoded barcodes on that page.

Does Dynamsoft Capture Vision report which page a barcode came from?

Yes. Each per-page CapturedResult includes an originalImageTag with a pageNumber (1-based in this sample) and totalPages. You can pair a decoded barcode with its page number, as the sample does when printing # Page N before the barcodes of each page.

Do I need to split a PDF into images before decoding?

No. The Dynamsoft Capture Vision SDK parses the PDF internally and decodes barcode candidates from each page’s rasterized content. captureMultiPagesAsync() iterates over every page automatically, so no third-party PDF rasterization or page-splitting step is required.

Which barcode formats does the Node.js PDF sample support?

The default PT_READ_BARCODES template covers 1D barcodes (Code 39, Code 93, Code 128, Codabar, ITF, EAN-8, EAN-13, UPC-A, UPC-E, Industrial 2 of 5, GS1 DataBar, Postal Codes) and 2D barcodes (QR Code, Micro QR, DataMatrix, PDF417, Micro PDF417, Aztec, MaxiCode, DotCode, Patch Code, GS1 Composite). The bundled barcodes.pdf test file demonstrates 12 of these formats.

Node.js Multi-Page PDF Barcode Reader Demo Video

Prerequisites

  • Node.js: Install the current LTS release from the Node.js website.
  • Dynamsoft Capture Vision SDK: The dynamsoft-capture-vision-for-node npm package and its model package are used for barcode decoding. Get a 30-day free trial license and update the LicenseManager.initLicense("LICENSE-KEY") line in index.js with your own key (or set the DCV_LICENSE environment variable).
  • A multi-page PDF file: Use the bundled barcodes.pdf shipping with the sample (5 pages, 17 barcodes), or any PDF you want to test.

Read 1D/2D barcodes from a multi-page PDF in Node.js

Step 1: Create the Project and Install Dependencies

Create a new Node.js project and install the Dynamsoft Capture Vision SDK:

npm init -y
npm install dynamsoft-capture-vision-for-node dynamsoft-capture-vision-for-node-model

Two packages are installed:

  • dynamsoft-capture-vision-for-node — the Capture Vision Router SDK that performs barcode decoding.
  • dynamsoft-capture-vision-for-node-model — the AI model package used by the read-rate-first preset template.

No native build step is involved: the packages ship precompiled binaries for Windows (x86/x64), Linux (x64/arm64), and macOS (x64/arm64) and load them at runtime through N-API.

Step 2: Write the Multi-Page PDF Barcode Reader

Create an index.js file with the following code:

const path = require('node:path');
const fs = require('node:fs');
const { LicenseManager, CaptureVisionRouter, EnumPresetTemplate } = require('dynamsoft-capture-vision-for-node');

// Get a 30-day free trial license:
// https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform
const LICENSE_KEY = process.env.DCV_LICENSE || 'YOUR-LICENSE-KEY';

async function main() {
  const pdfPath = process.argv[2];
  if (!pdfPath) {
    console.error('Usage: node index.js <pdf-file> [--template <name>] [--json <out.json>]');
    process.exit(1);
  }

  LicenseManager.initLicense(LICENSE_KEY);

  const template = process.argv.includes('--template')
    ? EnumPresetTemplate[process.argv[process.argv.indexOf('--template') + 1]]
    : EnumPresetTemplate.PT_READ_BARCODES;

  // Decode every page of the PDF: each page yields one CapturedResult.
  const results = await CaptureVisionRouter.captureMultiPagesAsync(pdfPath, template);

  const allBarcodes = [];
  results.forEach((result, pageIndex) => {
    console.log(`\n# Page ${pageIndex + 1}`);
    const items = result.barcodeResultItems || [];
    if (items.length === 0) {
      console.log('  No barcode found.');
      return;
    }
    for (const item of items) {
      console.log(`  Format     : ${item.formatString}`);
      console.log(`  Text       : ${item.text}`);
      console.log(`  Confidence : ${item.confidence}`);
      allBarcodes.push({
        page: pageIndex + 1,
        format: item.formatString,
        text: item.text,
        confidence: item.confidence,
        location: item.location.points.map(p => ({ x: p.x, y: p.y })),
      });
    }
  });

  console.log(`\nTotal barcodes decoded: ${allBarcodes.length}`);

  const jsonFlag = process.argv.indexOf('--json');
  if (jsonFlag !== -1 && process.argv[jsonFlag + 1]) {
    fs.writeFileSync(process.argv[jsonFlag + 1], JSON.stringify(allBarcodes, null, 2));
    console.log(`Results written to: ${process.argv[jsonFlag + 1]}`);
  }
}

main().catch((err) => {
  console.error(`Decoding failed: ${err.message || err}`);
  process.exitCode = 1;
}).finally(async () => {
  // Terminate workers so the process can exit.
  await CaptureVisionRouter.terminateIdleWorkers();
});

The two APIs that do all the work are:

Step 3: Run the Reader on a Multi-Page PDF

Run the script against the bundled barcodes.pdf test file:

node index.js barcodes.pdf

Real output on this test file (5 pages, 17 barcodes, trimmed for brevity):

# Page 1
  Decoded 1 barcode(s):
  Format     : QR_CODE
  Text       : www.dynamsoft.com
  Confidence : 85
  Location   : (2166, 36) (2340, 36) (2342, 212) (2166, 210)

# Page 5
  Decoded 13 barcode(s):
  Format     : CODE_128
  Text       : CODE128
  Confidence : 100
  Location   : (1498, 550) (2094, 552) (2094, 752) (1498, 750)
  Format     : PDF417
  Text       : www.dynamsoft.com
  Confidence : 84
  Location   : (452, 2698) (1360, 2698) (1360, 2978) (452, 2978)
  ...

Total barcodes decoded: 17
Elapsed time: 614 ms

Each page prints its header (# Page N), the decoded barcode format, text, confidence, and the four corner points of the barcode location. You can verify the page grouping independently: pages 1–4 each contain one QR Code, while page 5 contains the 13 remaining barcodes.

Export all results to a JSON file when you need the output for further processing:

node index.js barcodes.pdf --json result.json

The generated result.json is an array of objects (page, format, text, confidence, location), one per decoded barcode.

Step 4: Read with Different Preset Templates

Pass the --template flag to use a different preset template:

# Speed-optimized reading
node index.js barcodes.pdf --template PT_READ_BARCODES_SPEED_FIRST

# Read-rate-optimized reading (uses the AI model package)
node index.js barcodes.pdf --template PT_READ_BARCODES_READ_RATE_FIRST

# Single barcode per page
node index.js barcodes.pdf --template PT_READ_SINGLE_BARCODE
Template Purpose
PT_READ_BARCODES (default) Balanced barcode reading
PT_READ_BARCODES_SPEED_FIRST Speed-optimized reading, suitable for high volume
PT_READ_BARCODES_READ_RATE_FIRST Read-rate-optimized reading; uses the AI model package
PT_READ_SINGLE_BARCODE Detects a single barcode per page

Common Issues & Edge Cases

  • The process hangs after printing results: The Capture Vision SDK spawns a worker pool that keeps the Node.js event loop alive. Call await CaptureVisionRouter.terminateIdleWorkers() in a finally block (as the sample does) so the process can exit.
  • EC_LICENSE_INVALID or EC_LICENSE_KEY_NOT_MATCH on startup: The SDK validates the license against the LicenseManager.initLicense() value. Replace the placeholder in index.js or set the DCV_LICENSE environment variable, and make sure the license is a Dynamsoft Capture Vision trial or commercial key.
  • No barcodes detected on a scanned PDF: Low-resolution or heavily compressed PDFs produce barcodes too small to decode. Try the PT_READ_BARCODES_READ_RATE_FIRST template, which applies additional deblur and localization effort (and requires the dynamsoft-capture-vision-for-node-model package).
  • Slow decoding on very large PDFs: Each page is rasterized internally before localization. Use PT_READ_BARCODES_SPEED_FIRST for speed, or split the job per page: call captureMultiPagesAsync only on the page ranges you need, or use CaptureVisionRouter.captureAsync with a single-page extraction.
  • Multi-page TIFF support: captureMultiPagesAsync() also iterates over multi-page TIFF files, so the same code path handles .tif/.tiff documents.

Source Code

Get the complete sample project source code on GitHub: nodejs-barcode — see the examples/official/pdf directory for this multi-page PDF barcode reader, the bundled barcodes.pdf test file, and the full README. The sibling examples/official/command-line directory contains the single-image command-line reader built on the same SDK.