> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/get-started/frameworks/nodejs.md).

# Build a Node.js PDF library app with Apryse Server SDK

Learn how to build a simple Node.js PDF application using the Apryse Node.js PDF library and Server SDK to generate PDFs programmatically.

This guide shows how to build a simple Node.js PDF application that uses the [Apryse Server SDK](https://docs.apryse.com/try-now?tab-cfc13cf95cb8=server+%2F+desktop+sdk) and PDFNet library to generate a PDF programmatically. You’ll set up a minimal project, install the SDK, and add the required code to create a blank PDF document. This example provides a practical foundation for building more advanced document‑generation workflows.

To get started, choose your preferred platform from the tabs below.

{% tabs %}
{% tab title="Windows" %}

## Prerequisites

Before you start:

* Install [Visual Studio Code](https://code.visualstudio.com/Download) or another code editor to develop and debug your code.
* Install [Node.js and npm](https://nodejs.org/en/download) for your runtime environment. Use the latest active LTS version of Node.js within the supported range (Node.js 10.x–24.x).
* Get your Apryse trial key.

{% @apryse-license-key/apryse-license-key platform="SERVER" variant="full" %}

{% hint style="info" %}
**Run Apryse SDK in production**

A commercial license key is required for use in a production environment. [Contact sales](https://apryse.com/form/contact-sales) to purchase a commercial license key.
{% endhint %}

## 1. Set up your project

Set up your project by creating a folder and preparing your workspace for the application.

1. In your file manager, create a **Documents > NewApryseProject** folder.
2. Right-click the **NewApryseProject** folder and select **Open in Terminal.**
3. In your terminal, initialize a new Node.js project to generate a default `package.json` file:

{% code lineNumbers="true" %}

```shell
npm init -y
```

{% endcode %}

A successful output looks similar to:

{% code lineNumbers="true" %}

```shell
Wrote to <project_directory>/package.json:

{
  "name": "<project_name>",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs"
}

```

{% endcode %}

## 2. Add the Apryse SDK

Next, integrate the Apryse Server SDK into your Node.js application and add the code needed to generate a PDF.

1. Navigate to the `Documents\NewApryseProject` directory in your terminal, then install the Apryse SDK:

{% code lineNumbers="true" %}

```shell
npm i @pdftron/pdfnet-node
```

{% endcode %}

2. In Visual Studio Code, go to **File > New Text File**.
3. Paste this code into the text editor, update your license key, and save the file in the `Documents\NewApryseProject` directory as `index.js`:

<pre class="language-js" data-line-numbers><code class="lang-js">console.log("Hello World from Node.js!");

// You may need to set up NODE_PATH environment variable to make this work
const { PDFNet } = require('@pdftron/pdfnet-node');

const main = async () => {
  const doc = await PDFNet.PDFDoc.create();
  const page = await doc.pageCreate();
  doc.pagePushBack(page);
  doc.save('output.pdf', PDFNet.SDFDoc.SaveOptions.e_linearized);
};

// Add your own license key as the second parameter, e.g. in place of '<code class="expression">visitor.claims.serverKey || "YOUR_LICENSE_KEY"</code>'
PDFNet.runWithCleanup(main, '<code class="expression">visitor.claims.serverKey || "YOUR_LICENSE_KEY"</code>')
  .catch((error)=> {
    console.log('Error: ' + JSON.stringify(error));
  })
  .then(()=> {
    PDFNet.shutdown();
  });
</code></pre>

{% hint style="info" %}
**Info**

If you're signed in with an Apryse account, your license key is automatically prepopulated in all code snippets.
{% endhint %}

With this code, you can:

* Log a startup message to confirm the application is running.
* Import the Apryse Node.js SDK.
* Define an asynchronous `main` function that creates a new PDF document, adds a blank page, and saves it as a linearized PDF.
* Use `runWithCleanup` to initialize the SDK, execute the main function, and handle cleanup automatically.
* Handle errors and shut down the `PDFNet` engine after execution to release resources.

## 3. Verify your output

Finally, build and run your application to confirm that the Apryse Server SDK is working correctly. After the application runs successfully, it will generate a blank PDF file locally.

1. Go to the **Documents > NewApryseProject** folder, and right-click to select **Open in Terminal**.
2. In the terminal, build and launch the application:

{% code lineNumbers="true" %}

```shell
node index.js
```

{% endcode %}

A successful output looks similar to:

{% code lineNumbers="true" %}

```shell
Hello World from Node.js!

PDFNet is running in demo mode.
PackageV2: base
```

{% endcode %}

3. Go to the **Documents >** **NewApryseProject** folder using the file manager.
4. Verify the blank `output.pdf` file was generated programmatically using the Apryse Server SDK:

{% code lineNumbers="true" %}

```
NewApryseProject/
├── node_modules/
├── index.js
├── output.pdf
├── package.json
└── package-lock.json
```

{% endcode %}
{% endtab %}

{% tab title="Linux" %}
{% tabs %}
{% tab title="Node.js" %}

## Prerequisites

Before you start:

* Install [Visual Studio Code](https://code.visualstudio.com/Download) or another code editor to develop and debug your code.
* Install [Node.js and npm](https://nodejs.org/en/download) for your runtime environment. Use the latest active LTS version of Node.js within the supported range (Node.js 10.x–24.x).
* Get your Apryse trial key.

{% @apryse-license-key/apryse-license-key platform="SERVER" variant="full" %}

{% hint style="info" %}
**Run Apryse SDK in production**

A commercial license key is required for use in a production environment. [Contact sales](https://apryse.com/form/contact-sales) to purchase a commercial license key.
{% endhint %}

{% hint style="warning" %}
**Keep your commercial license key confidential**

License keys are uniquely generated and strictly confidential. Don't publish or store them in any public location, including public GitHub repositories.
{% endhint %}

## 1. Set up your project

Set up your project by creating a folder and preparing your workspace for the application.

1. In your file manager, create a **Documents > NewApryseProject** folder.
2. Right-click the **NewApryseProject** folder and select **Open in Terminal**.
3. In your terminal, initialize a new Node.js project to generate a default `package.json` file:

{% code lineNumbers="true" %}

```bash
npm init -y
```

{% endcode %}

A successful output looks similar to:

{% code lineNumbers="true" %}

```bash
Wrote to <project_directory>/package.json:

{
  "name": "<project_name>",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs"
}

```

{% endcode %}

## 2. Add the Apryse SDK

Next, integrate the Apryse Server SDK into your Node.js application and add the code needed to generate a PDF.

1. Navigate to the `Documents/NewApryseProject` directory in your terminal, then install the Apryse SDK:

{% code lineNumbers="true" %}

```bash
npm i @pdftron/pdfnet-node
```

{% endcode %}

2. In Visual Studio Code, go to **File > New Text File**.
3. Paste this code into the text editor, update your license key, and save the file in the `Documents/NewApryseProject` directory as `index.js`:

<pre class="language-js" data-line-numbers><code class="lang-js">console.log("Hello World from Node.js!");

// You may need to set up NODE_PATH environment variable to make this work
const { PDFNet } = require('@pdftron/pdfnet-node'); 

const main = async () => {
  const doc = await PDFNet.PDFDoc.create();
  const page = await doc.pageCreate();
  doc.pagePushBack(page);
  doc.save('output.pdf', PDFNet.SDFDoc.SaveOptions.e_linearized);
};

// Add your own license key as the second parameter, e.g. in place of '<code class="expression">visitor.claims.serverKey || "YOUR_LICENSE_KEY"</code>'
PDFNet.runWithCleanup(main, '<code class="expression">visitor.claims.serverKey || "YOUR_LICENSE_KEY"</code>')
  .catch((error)=> {
    console.log('Error: ' + JSON.stringify(error));
  })
  .then(()=> {
    PDFNet.shutdown();
  });
</code></pre>

{% hint style="info" %}
**Info**

If you're signed in with an Apryse account, your license key is automatically prepopulated in all code snippets.
{% endhint %}

With this code, you can:

* Log a startup message to confirm the application is running.
* Import the Apryse Node.js SDK.
* Define an asynchronous `main` function that creates a new PDF document, adds a blank page, and saves it as a linearized PDF.
* Use `runWithCleanup` to initialize the SDK, execute the main function, and handle cleanup automatically.
* Handle errors and shut down the `PDFNet` engine after execution to release resources.

## 3. Verify your output

Finally, build and run your application to confirm that the Apryse Server SDK is working correctly. After the application runs successfully, it will generate a blank PDF file locally.

1. Go to the **Documents > NewApryseProject** folder, and right-click to select **Open in Terminal**.
2. In the terminal, build and launch the application:

{% code lineNumbers="true" %}

```bash
node index.js
```

{% endcode %}

A successful output looks similar to:

{% code lineNumbers="true" %}

```bash
Hello World from Node.js!

PDFNet is running in demo mode.
PackageV2: base
```

{% endcode %}

3. Go to the **Documents** > **NewApryseProject** folder using the file manager.
4. Verify the blank `output.pdf` file was generated programmatically using the Apryse Server SDK:

{% code lineNumbers="true" %}

```
NewApryseProject/
├── node_modules/
├── index.js
├── output.pdf
├── package.json
└── package-lock.json
```

{% endcode %}
{% endtab %}

{% tab title="AWS Lambda Functions" %}

## Prerequisites

* A version of [Node.js](https://nodejs.org/en/about/previous-releases) supported by AWS Lambda (up to v24)
* An active [AWS account](https://aws.amazon.com/lambda/getting-started/)
* [Docker](https://www.docker.com/) (optional)

## Initial Setup

In this particular guide, we will demonstrate how to set up an AWS Lambda function to use the Apryse SDK with Node.js.

First, you will have to prepare a deployment package with the `pdfnet-node` module and your Lambda function code (typically named `index.js`) within it. From the command line:

{% code lineNumbers="true" %}

```sh
mkdir YOUR_FUNCTION_FOLDER
cd YOUR_FUNCTION_FOLDER
npm init -y
npm install @pdftron/pdfnet-node
```

{% endcode %}

Now, copy your lambda function code to `YOUR_FUNCTION_FOLDER`.

It's at this point that it is important to note that the `pdfnet-node` module must be installed using the same operating system that AWS Lambda will use for its runtime. This is dependent on on the version of Node.js you are using. To see which operating system is required, look [here](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html).

We recommend that you use a Docker container to simulate this runtime and have included a Dockerfile to do just that. Create a Dockerfile with the contents below.

{% code title="Dockerfile" lineNumbers="true" %}

```dockerfile
# Declare the build argument
ARG NODE_VERSION=18

# Stage #1: Build the Lambda function deployment package
FROM public.ecr.aws/lambda/nodejs:$NODE_VERSION AS build-stage

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json for caching dependencies
COPY package.json ./
COPY package-lock.json ./

# Install node dependencies for production
RUN npm ci --omit=dev

# Copy Lambda function code into the working directory
COPY index.js ./

# Stage #2: Package the Lambda function deployment package into a .zip file
FROM alpine

# Set the working directory
WORKDIR /app

# Install packaging dependencies and make output directory
RUN apk add --no-cache zip && \
    mkdir /output

# Copy Lambda function code file and node_modules from build stage into working directory
COPY --from=build-stage /app/index.js ./
COPY --from=build-stage /app/node_modules/ ./node_modules/

# Create a deployment package (a .zip file) that will be uploaded to AWS Lambda when the container is made
CMD ["zip", "-r", "/output/deploymentpackage.zip", "./"]
```

{% endcode %}

Next, run the following docker commands to generate a deployment package to upload to AWS Lambda. Replace `YOUR_IMAGE_NAME_HERE` with the image name of your choice, as well as `YOUR_NODE_VERSION_HERE` as the Node version of your choice. `YOUR_NODE_VERSION_HERE` as the Node version of your choice. Note that this Dockerfile requires that your AWS Lambda function code file be named `index.js`, and that it uses your project's package.json and package-lock.json to install dependencies such as the `pdfnet-node` module you installed in the last step.

{% code lineNumbers="true" %}

```sh
docker build -t YOUR_IMAGE_NAME_HERE --build-arg NODE_VERSION=YOUR_NODE_IMAGE_HERE .
docker run --rm -v $(pwd)/output:/output YOUR_IMAGE_NAME_HERE
```

{% endcode %}

After running this Docker container, you should have your deployment package within the ./output directory and can now upload it to AWS Lambda.

Second, create a Lambda function in your AWS account and upload the deployment package:

* Lambda > Functions > Create function > Author from scratch > Function name \[`YOUR_FUNCTION_NAME`] > Runtime (matching your Node version) > choose Create Function
* Upload from .zip file > Upload \[your deployment package] > Save
* Add trigger > API Gateway > Create an API > REST > Security \[Open]
* Configuration > General configuration > Edit > memory \[Choose 10240MB]

## Integrate Into Your Application

Once you have followed the initial setup instructions, you can begin calling Apryse SDK APIs in your Lambda function code. For example:

{% code lineNumbers="true" %}

```js
const { PDFNet } = require('@pdftron/pdfnet-node');
exports.handler = async (event) => {
  let response = null;
  if (event.httpMethod != 'POST') {
    response = {
      statusCode: 200,
      body: JSON.stringify('Hello, your AWS lambda function is working!'),
    };
  } else {
    const main = async () => {
      // parsing
      let body = JSON.parse(event.body);
      // your AWS lambda function goes here
      response = {
        statusCode: 200,
        body: JSON.stringify('your AWS lambda function response.'),
      };
    };
    await PDFNet.runWithCleanup(main, 'YOUR_PDFTRON_LICENSE_KEY_HERE').catch(
      function (error) {
        console.log('Error: ' + JSON.stringify(error));
        response = {
          statusCode: 500,
          body: JSON.stringify(error),
        };
      }
    );
  }
  return response;
};
```

{% endcode %}

## Run Sample Code

You can update the Node.js script of your AWS Lambda function with the following code or download the [source code from our GitHub repository](https://github.com/PDFTron/aws-function-example/tree/main/server-nodejs/). This snippet shows how to process a request sent from a client, convert an office document to a PDF, and send the output to client.

{% code lineNumbers="true" %}

```js
// This example shows how to create AWS Lambda functions using Apryse SDK.
// A REST API request was posted with base64 encoded data by the client.
// The request would be processed by the server and a response with base64 encoded data of OfficeToPDF output would be sent to the client.
const { PDFNet } = require('@pdftron/pdfnet-node');
exports.handler = async (event) => {
  let response = null;
  if (event.httpMethod != 'POST') {
    response = {
      statusCode: 200,
      body: JSON.stringify(
        'Hello, please send base64 doc to use this Lambda function!'
      ),
    };
  } else {
    const main = async () => {
      // parsing
      let body = JSON.parse(event.body);
      let base64str = body.file.data;
      let filename = body.file.filename;
      let base64_bytes = Buffer.from(base64str, 'base64');
      // save input doc to /tmp
      const outputPath = '/tmp/';
      const path = require('path');
      const inputFilename = path.parse(filename).name + '.docx';
      const fs = require('fs');
      fs.writeFileSync(outputPath + inputFilename, base64_bytes);
      // perform the conversion with no optional parameters
      const pdfdoc = await PDFNet.Convert.officeToPdfWithPath(
        outputPath + inputFilename
      );
      // save the result
      const outputFilename = path.parse(filename).name + '.pdf';
      await pdfdoc.save(
        outputPath + outputFilename,
        PDFNet.SDFDoc.SaveOptions.e_linearized
      );
      console.log('Saved ' + outputFilename);
      // sending data
      let buff = fs.readFileSync(outputPath + outputFilename);
      let base64_string = buff.toString('base64');
      response = {
        statusCode: 200,
        body: JSON.stringify(base64_string),
      };
    };
    await PDFNet.runWithCleanup(main, 'YOUR_PDFTRON_LICENSE_KEY_HERE').catch(
      function (error) {
        console.log('Error: ' + JSON.stringify(error));
        response = {
          statusCode: 500,
          body: JSON.stringify(error),
        };
      }
    );
  }
  return response;
};
```

{% endcode %}

### Testing

After you have uploaded your deployment package to AWS Lambda and set its `API endpoint` in Configuration > Triggers, you can now do a simple test using a REST API.

In order to use the function to convert an office document to PDF, the client needs to `POST` a REST API request to the server. The request must include JSON data structured as in the code below.

{% code lineNumbers="true" %}

```python
json_data = {
  "file": {
    "encoding": "base64",
    "data": base64_string_of_your_office_document,
    "filename": filename,
    "content-type": "application/pdf"
  }
}
```

{% endcode %}

Upon receiving a client's request, a response will be sent back to the client including the base64 encoded PDF output using the same JSON structure. All the client needs to do now is decode the encoded data into a PDF. That's it! Please review the [sample python code](https://github.com/PDFTron/aws-function-example/tree/main/client/). After cloning the repository and installing necessary packages, please refer to `/client/README.txt` for detailed instructions. Navigate to the `client` folder, run the following command, see the response to client's request in the console, and check the output in the `output` folder:

{% code lineNumbers="true" %}

```python
python AWSLambdaExample.py --url <YOUR PUBLISHED FUNCTION URL>
```

{% endcode %}

The client will send a REST API request to convert `/input/simple-word_2007.docx` to a PDF and the server will send back the encoded data, which will then be saved as PDF in the `output` folder.

You can experiment with your own office document by putting it inside `input` folder:

{% code lineNumbers="true" %}

```python
python AWSLambdaExample.py --url <YOUR PUBLISHED FUNCTION URL> --filename <YOUR OFFICE FILENAME>
```

{% endcode %}

In this article, we have shown how to set up an AWS Lambda function using the Apryse SDK. You can now experiment making your own functions, URLs, and can fully utilize the Apryse SDK using AWS Lambda. If your have any questions, please don't hesitate to contact us!
{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="macOS" %}

## Prerequisites

Before you start:

* Install [Visual Studio Code](https://code.visualstudio.com/Download) or another code editor to develop and debug your code.
* Install [Node.js and npm](https://nodejs.org/en/download) for your runtime environment. Use the latest active LTS version of Node.js within the supported range (Node.js 10.x–24.x).
* Get your Apryse trial key.

{% @apryse-license-key/apryse-license-key platform="SERVER" variant="full" %}

{% hint style="info" %}
**Run Apryse SDK in production**

A commercial license key is required for use in a production environment. [Contact sales](https://apryse.com/form/contact-sales) to purchase a commercial license key.
{% endhint %}

{% hint style="warning" %}
**Keep your commercial license key confidential**

License keys are uniquely generated and strictly confidential. Don't publish or store them in any public location, including public GitHub repositories.
{% endhint %}

## 1. Set up your project

Set up your project by creating a folder and preparing your workspace for the application.

1. In your file manager, create a **Documents > NewApryseProject** folder.
2. Right-click the **NewApryseProject** folder and select **New Terminal at Folder**.
3. In your terminal, initialize a new Node.js project to generate a default `package.json` file:

{% code lineNumbers="true" %}

```bash
npm init -y
```

{% endcode %}

A successful output looks similar to:

{% code lineNumbers="true" %}

```bash
Wrote to <project_directory>/package.json:

{
  "name": "<project_name>",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs"
}

```

{% endcode %}

## 2. Add the Apryse SDK

Next, integrate the Apryse Server SDK into your Node.js application and add the code needed to generate a PDF.

1. Navigate to the `Documents/NewApryseProject` directory in your terminal, then install the Apryse SDK:

{% code lineNumbers="true" %}

```bash
npm i @pdftron/pdfnet-node
```

{% endcode %}

2. In Visual Studio Code, go to **File > New Text File**.
3. Paste this code into the text editor, update your license key, and save the file in the `Documents/NewApryseProject` directory as `index.js`:

<pre class="language-js" data-line-numbers><code class="lang-js">console.log("Hello World from Node.js!");

// You may need to set up NODE_PATH environment variable to make this work
const { PDFNet } = require('@pdftron/pdfnet-node');

const main = async () => {
  const doc = await PDFNet.PDFDoc.create();
  const page = await doc.pageCreate();
  doc.pagePushBack(page);
  doc.save('output.pdf', PDFNet.SDFDoc.SaveOptions.e_linearized);
};

// Add your own license key as the second parameter, e.g. in place of '<code class="expression">visitor.claims.serverKey || "YOUR_LICENSE_KEY"</code>'
PDFNet.runWithCleanup(main, '<code class="expression">visitor.claims.serverKey || "YOUR_LICENSE_KEY"</code>')
  .catch((error)=> {
    console.log('Error: ' + JSON.stringify(error));
  })
  .then(()=> {
    PDFNet.shutdown();
  });
</code></pre>

{% hint style="info" %}
**Info**

If you're signed in with an Apryse account, your license key is automatically prepopulated in all code snippets.
{% endhint %}

With this code, you can:

* Log a startup message to confirm the application is running.
* Import the Apryse Node.js SDK.
* Define an asynchronous `main` function that creates a new PDF document, adds a blank page, and saves it as a linearized PDF.
* Use `runWithCleanup` to initialize the SDK, execute the main function, and handle cleanup automatically.
* Handle errors and shut down the `PDFNet` engine after execution to release resources.

## 3. Verify your output

Finally, build and run your application to confirm that the Apryse Server SDK is working correctly. After the application runs successfully, it will generate a blank PDF file locally.

1. Go to the **Documents > NewApryseProject** folder, and right-click to select **New Terminal at Folder**.
2. In the terminal, build and launch the application:

{% code lineNumbers="true" %}

```bash
node index.js
```

{% endcode %}

A successful output looks similar to:

{% code lineNumbers="true" %}

```bash
Hello World from Node.js!

PDFNet is running in demo mode.
PackageV2: base
```

{% endcode %}

3. Go to the **Documents >** **NewApryseProject** folder using the file manager.
4. Verify the blank `output.pdf` file was generated programmatically using the Apryse Server SDK. The folder structure looks similar to:

{% code lineNumbers="true" %}

```
NewApryseProject/
├── node_modules/
├── index.js
├── output.pdf
├── package.json
└── package-lock.json
```

{% endcode %}
{% endtab %}
{% endtabs %}

## **Get started video**

Get started with the Apryse Server SDK and Node.js on the Windows platform by watching this 4-minute video.

{% embed url="<https://www.youtube.com/embed/tHx8qfFm3y4?si=0C1dYcu7nN0pjNNs>" %}
Get started video for Apryse Server SDK and Node.js on Windows
{% endembed %}

## Next Steps

<a href="/core/basic-operations/basics.md" class="button primary">Usage</a><a href="/core/get-started/readme.md" class="button primary">Guides</a><a href="/core/get-started/samples.md" class="button primary">Samples</a><a href="/core/get-started/readme/api.md" class="button primary">API docs</a>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/get-started/frameworks/nodejs.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
