The PDF SDK runs natively in Node.js for server-side PDF processing — creating, editing, merging, and extracting content without a browser.
File and fetch support)"type": "module" in your package.json)npm install @avanquest/pdf-web-viewer
The SDK auto-detects worker and font assets from node_modules — no asset copying needed:
import { PdfSdk } from '@avanquest/pdf-web-viewer/sdk';
await PdfSdk.initialize({
license: 'YOUR_LICENSE_KEY',
});
That's it! The SDK will automatically find the worker and font files in node_modules/@avanquest/pdf-web-viewer/public/.
All accepted options of PdfSdk.initialize(options):
| Option | Type | Description |
|---|---|---|
license (required) |
string |
License key. Validated on first call against the licensing server. |
basePath |
string |
Absolute path to the parent directory containing pwv-workers/ and pwv-fonts/. Default: auto-detect. |
logging |
boolean |
If true, enables verbose [PDFWORKER] … debug output from the WASM worker. Useful for diagnosing initialization failures. |
openDocumentsInNewTab |
boolean |
UI-only flag; ignored in headless Node.js usage. |
If you prefer to host assets separately (e.g., for Docker or CI environments), point basePath at the
absolute filesystem path of the parent directory that contains your copied pwv-workers/ and pwv-fonts/
folders:
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
await PdfSdk.initialize({
license: 'YOUR_LICENSE_KEY',
basePath: resolve(__dirname, 'assets'), // Parent dir containing pwv-workers/ and pwv-fonts/
});
Copy assets from the package into that directory:
mkdir -p ./assets
cp -R ./node_modules/@avanquest/pdf-web-viewer/public/pwv-workers ./assets/pwv-workers
cp -R ./node_modules/@avanquest/pdf-web-viewer/public/pwv-fonts ./assets/pwv-fonts
import express from 'express';
import { PdfSdk } from '@avanquest/pdf-web-viewer/sdk';
import { readFileSync } from 'fs';
const app = express();
// Initialize SDK once at startup
await PdfSdk.initialize({
license: process.env.PDF_LICENSE_KEY,
});
// Create a blank PDF
app.get('/create-blank', async (req, res) => {
const document = await PdfSdk.openBlankDocument({
name: 'New Document.pdf',
numPages: 3,
Rectangle: [0, 792, 612, 0], // Letter size
PDFVersion: '2.0',
});
const bytes = await document.exportDocument({ as: 'uint8array' });
await document.dispose();
res.setHeader('Content-Type', 'application/pdf');
res.send(Buffer.from(bytes));
});
// Open and process an existing PDF
app.post('/process', async (req, res) => {
const pdfBuffer = readFileSync('/path/to/input.pdf');
const file = new File([pdfBuffer], 'document.pdf', { type: 'application/pdf' });
const document = await PdfSdk.openDocument({ file });
// Delete first page
await document.deletePages({ range: [0] });
// Export result
const result = await document.exportDocument({ as: 'uint8array' });
await document.dispose();
res.setHeader('Content-Type', 'application/pdf');
res.send(Buffer.from(result));
});
// List available fonts
app.get('/fonts', async (req, res) => {
const fonts = await PdfSdk.listSystemFonts();
res.json({ fontCount: fonts.length, fonts });
});
app.listen(8080, () => console.log('Server running on http://localhost:8080'));
The SDK resolves the pwv-workers/ and pwv-fonts/ folders in the following order:
| Priority | Source |
|---|---|
| 1 | Custom basePath option, if set — <basePath>/pwv-workers/ and <basePath>/pwv-fonts/ |
| 2 | Auto-detect from cwd and node_modules/@avanquest/pdf-web-viewer/public/ |
package.json must have "type": "module", or use .mjs file extensions.https://api-developers.avanquest.com over HTTPS. The validation request is synchronous (Node spawns a short-lived child process to perform it) and does not honor HTTP_PROXY / HTTPS_PROXY environment variables — if you sit behind a corporate proxy, surface the SDK from outside it.document.dispose() when done to prevent memory leaks.PdfSdk.initialize() once at startup. All subsequent operations share the same worker instance.Cannot reach the licensing server (errorCode 18) on startupThe WASM worker performs the license check using a synchronous HTTPS request. If it fails:
node -e "require('https').get('https://api-developers.avanquest.com', r => console.log(r.statusCode))"
Expect a 2xx/4xx response. A network/DNS error here means the licensing host is unreachable.logging: true to PdfSdk.initialize(...) to surface [PDFWORKER] … debug lines from the worker.If you see errors about pdfworker-*.wasm or pdfworker-*.data being missing:
<basePath>/pwv-workers/ (the default location, or your custom basePath) contains all three pdfworker-* files.basePath you pass must be absolute. Use resolve(__dirname, 'assets') rather than a relative string.pwv-workers/ directory — the hashed filenames must match the ones this SDK build expects (they are embedded into the bundle at build time).