PDF to PDF in Node.js

Overview

Merge, split and modify PDF documents with the PDFCrowd Node.js client. The client handles communication with the API, while processing runs on PDFCrowd's servers.

Installation

Install the Node.js client with npm, or see other installation options.

npm install pdfcrowd

Quick Start

Update the input URLs and filenames as needed.

Merge PDFs

Merge a cover, proposal, price list and contact page in that order, then save the PDF locally as offer.pdf:

const pdfcrowd = require('pdfcrowd');

const client = new pdfcrowd.PdfToPdfClient("demo", "demo");

client.addPdfFile("cover.pdf");
client.addPdfFile("proposal.pdf");
client.addPdfFile("price.pdf");
client.addPdfFile("contact.pdf");
client.convertToFile("offer.pdf", (error) => {
    if (error) {
        console.error(error.toString());
        return;
    }
});

The output file is ready when the callback runs without an error. Put code that uses the file inside that callback. The callback receives a pdfcrowd.Pdfcrowd.Error on failure. Validation can also throw an exception. See Handle Errors.

Add a Watermark

Place the first page of watermark.pdf over every page of proposal.pdf and save the PDF locally as company_offer.pdf:

const pdfcrowd = require('pdfcrowd');

const client = new pdfcrowd.PdfToPdfClient("demo", "demo");

client.setPageWatermark("watermark.pdf");
client.addPdfFile("proposal.pdf");
client.convertToFile("company_offer.pdf", (error) => {
    if (error) {
        console.error(error.toString());
        return;
    }
});

Extract Pages

Extract page 3 and pages 7 through the end of a PDF, then save them locally as output.pdf:

const pdfcrowd = require('pdfcrowd');

const client = new pdfcrowd.PdfToPdfClient("demo", "demo");

client.setAction("extract");
client.setPageRange("3,7-");
client.addPdfFile("13_pages.pdf");
client.convertToFile("output.pdf", (error) => {
    if (error) {
        console.error(error.toString());
        return;
    }
});

Configure a Conversion

Authentication

Pass your PDFCrowd username and API key to PdfToPdfClient. Find your credentials on the API Keys page.

Add Input PDFs

Add each PDF before calling a conversion method. The default action joins the documents in the order they were added.

InputMethod
Local PDF fileaddPdfFile()
PDF bytes in memoryaddPdfRawData()

For encrypted input PDFs, set the document password with setInputPdfPassword() before conversion. This is separate from your API key and the passwords used to protect the output PDF.

Send PDF Bytes

Read two local PDFs as bytes, merge them in order, and save the result locally as merged.pdf:

const fs = require("node:fs");
const pdfcrowd = require("pdfcrowd");

const client = new pdfcrowd.PdfToPdfClient("demo", "demo");

client.addPdfRawData(fs.readFileSync("cover.pdf"));
client.addPdfRawData(fs.readFileSync("proposal.pdf"));
client.convertToFile("merged.pdf", (error) => {
    if (error) {
        console.error(error.toString());
        return;
    }
});

Add Conversion Settings

Set conversion options on the client before calling a conversion method. For example, client.setLinearize(true); optimizes the output PDF for progressive loading.

Common settings are listed below. See the method reference for all available options or browse Node.js examples.

PurposeMethods
Join, interleave, extract or delete pagessetAction(), setPageRange()
Watermark and backgroundsetPageWatermark(), setPageBackground(), setMultipageWatermark(), setMultipageBackground()
Optimize for progressive loadingsetLinearize()
Output protectionsetEncrypt(), setUserPassword(), setOwnerPassword(), setNoCopy(), setNoPrint()
Metadata and attachmentssetTitle(), setAuthor(), setUseMetadataFrom(), addAttachment()

Use "extract" with a page range to keep selected pages, or "delete" to remove them. The "shuffle" action interleaves pages from the input PDFs.

Handle the Result

Choose an Output

After adding the inputs and settings, choose how to receive the PDF:

OutputMethod
Local fileconvertToFile()
Readable streamconvert(), with a data(stream) callback

Pipe the response stream to a writable stream or collect its chunks in a Buffer. The end callback runs when the response finishes.

This example merges two PDFs, collects the result in a Buffer, and saves it locally as merged.pdf:

const fs = require("node:fs");
const pdfcrowd = require("pdfcrowd");

const client = new pdfcrowd.PdfToPdfClient("demo", "demo");

client.addPdfFile("cover.pdf");
client.addPdfFile("proposal.pdf");
const chunks = [];
client.convert({
    data: (stream) => stream.on("data", (chunk) => chunks.push(chunk)),
    error: (message, statusCode) => {
        console.error(new pdfcrowd.Pdfcrowd.Error(String(message), statusCode).toString());
    },
    end: () => {
        const result = Buffer.concat(chunks);
        fs.writeFileSync("merged.pdf", result);
    }
});

When serving the result from a web application, use Content-Type: application/pdf.

Handle Errors

File-output methods pass a pdfcrowd.Pdfcrowd.Error to their callback on failure and null on success. Validation can also throw an exception. This example merges two PDFs and handles both paths, logging the HTTP status and reason code when available:

const pdfcrowd = require("pdfcrowd");

const client = new pdfcrowd.PdfToPdfClient("demo", "demo");

function handleError(error) {
    if (error instanceof pdfcrowd.Pdfcrowd.Error) {
        console.error("PDFCrowd error:", error.getStatusCode(),
            error.getReasonCode(), error.getMessage());
    } else {
        console.error(error);
    }
}

try {
    client.addPdfFile("cover.pdf");
    client.addPdfFile("proposal.pdf");
    client.convertToFile("merged.pdf", (error) => {
        if (error) {
            handleError(error);
            return;
        }
    });
} catch (error) {
    handleError(error);
}

Stream-output methods call error(message, statusCode) on failure. Local file and stream errors may need separate handling.

pdfcrowd.Pdfcrowd.Error provides these methods:

MethodReturns
getStatusCode()The HTTP status code, when available.
getReasonCode()The reason code identifying the specific error, or -1 if unavailable.
getMessage()The error message.
getDocumentationLink()A link to relevant documentation, when available.

error.toString() returns the complete error, including available status and reason codes.

Common Status Codes

StatusWhat it meansWhat to do
400Invalid input, settings, or conversion failureRead the reason code and correct the input or settings.
401Missing credentials or an inactive licenseCheck your username, API key, and license status.
403Suspended service or no credits remainingCheck your account and available credits.
413Upload exceeds the 300 MB limitReduce the upload size.
429Request rate limit reachedWait and reduce the rate of new requests.
430Concurrent request limit reachedAllow active requests to finish before starting more.
503Temporary network issueCheck your retry policy before submitting another request.

See all status and reason codes for specific explanations and Limits and Retries for retry behavior.

Read Conversion Information

This information is available after a conversion and describes the client's last conversion. Read it in the completion or error callback.

MethodUse
getJobId()Identify the conversion in logs and support requests.
getDebugLogUrl()The URL of the conversion debug log when logging is enabled.
getPageCount()Read the number of pages in the PDF.
getOutputSize()Read the PDF size in bytes.
getConsumedCreditCount()Read the credits consumed by the conversion.
getRemainingCreditCount()Read the remaining credit count reported with the conversion.

Limits and Retries

Request rate and concurrency limits depend on your license. Control how quickly your application submits conversions and how many it runs at once. A 429 response concerns request rate; a 430 response concerns requests already in progress. The maximum upload size is 300 MB.

The Node.js client automatically retries a request once when it receives HTTP 502 or 503. Use setRetryCount() to change that count, or set it to 0 to disable automatic retries. Account for these retries when adding an application-level retry policy.

Troubleshooting

Inspect a Conversion

This example merges two PDFs with debug logging enabled and logs the debug log URL when available. Use the input and settings from the conversion you are investigating.

const pdfcrowd = require("pdfcrowd");

const client = new pdfcrowd.PdfToPdfClient("demo", "demo");

function finish(error) {
    if (error) {
        console.error(error.toString());
    }
    const debugLogUrl = client.getDebugLogUrl();
    if (debugLogUrl) console.info("Debug log:", debugLogUrl);
}

try {
    client.addPdfFile("cover.pdf");
    client.addPdfFile("proposal.pdf");
    client.setDebugLog(true);
    client.convertToFile("merged.pdf", finish);
} catch (error) {
    finish(error);
}

The debug log contains conversion settings and processing details. You can also find logs in your conversion history. A local or connection failure may occur before a conversion log is available.

Common Problems

ProblemCheck
The PDF cannot be readCheck file paths, read permissions and whether each input is a valid PDF. For encrypted inputs, use setInputPdfPassword().
Pages are missing or in the wrong orderCheck the order of added PDFs, the selected action and the page range. Use the default join action to append documents, or "shuffle" to interleave their pages.
The watermark hides the documentA watermark is placed over the page. Use a transparent watermark or setPageBackground() to place content behind the page.

For help, contact support and include any available diagnostics, the client version, and enough detail to reproduce the problem.