Blog Post

How to Use JavaScript to Capture Signatures in PDFs

Illustration: How to Use JavaScript to Capture Signatures in PDFs

In this tutorial, you’ll walk through the process of creating a web-based app that enables users to capture and save signatures as images, as well as insert these signatures into a PDF document. You’ll be using HTML, JavaScript, and two external libraries — Signature Pad and pdf-lib — to achieve this functionality. The app will provide a canvas for users to draw their signatures, save them as PNG images, and embed them into a PDF for download.

In the second part, you’ll explore using the PSPDFKit JavaScript PDF library to incorporate electronic signatures (eSignatures) into PDF documents. The post will cover:

  • Adding eSignatures via the User Interface (UI)

  • Adding eSignatures Programmatically

  • Adding Ink Signatures Programmatically

  • Adding Image Signatures Programmatically

  • Creating Signature Fields in PDF Documents

Step 1 — Setting Up the HTML Structure

To begin, set up a basic HTML file. Include a canvas element that acts as a signature pad and a placeholder div to display the PDF. Additionally, add the necessary JavaScript libraries — Signature Pad and pdf-lib — which will be crucial for signature drawing and PDF manipulation:

<!DOCTYPE html>
<html>
	<head>
		<title>Signature Capture</title>
		<!-- Include Signature Pad library -->
		<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/signature_pad.umd.min.js"></script>
		<!-- Include pdf-lib library -->
		<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.16.0/pdf-lib.min.js"></script>
	</head>
	<body>
		<!-- Placeholder for PDF display -->
		<div id="pdfViewer"></div>
		<!-- Signature Canvas -->
		<canvas id="signatureCanvas" width="400" height="200"></canvas>
		<!-- Add a button to trigger signature saving and insertion -->
		<button onclick="saveSignatureAndInsertIntoPDF()">
			Save Signature and Insert into PDF
		</button>
		<script>
			// JavaScript code will be added here.
		</script>
	</body>
</html>

Step 2 — Initializing the Signature Pad

In your JavaScript section, access the canvas element and initialize the signature pad:

// Accessing the canvas element.
const signatureCanvas = document.getElementById('signatureCanvas');
const signaturePad = new SignaturePad(signatureCanvas);

This enables you to interact with the canvas and capture user-drawn signatures.

Step 3 — Saving the Signature as an Image

When users click the Save Signature and Insert into PDF button, you’ll capture the signature from the canvas as an image and save it for further use. You achieve this by calling the toDataURL method of the signature pad and creating a temporary link element to initiate the download:

// Function to save the signature as an image and insert it into the PDF.
async function saveSignatureAndInsertIntoPDF() {
	const signatureDataUrl = signaturePad.toDataURL('image/png');
	// You can now send this data to the server for processing or save it locally.
	console.log(signatureDataUrl); // Log the signature data URL for demonstration purposes.

	// Call the function to insert the signature into the PDF.
	const modifiedPDFBytes = await insertSignatureIntoPDF(
		signatureDataUrl,
	);

	// Download the modified PDF with the inserted signature.
	downloadModifiedPDF(modifiedPDFBytes);
}

Step 4 — Inserting the Signature into the PDF

To embed the signature image into a PDF, you’ll use the pdf-lib library. Load the existing PDF document from a file and convert it to a Uint8Array. Then, embed the signature image as a custom image using the embedPng method. Finally, add the image to the PDF document at the desired position:

// Function to insert the signature into the PDF.
async function insertSignatureIntoPDF(signatureDataURL) {
	const pdfBytes = await fetch('document.pdf').then((res) =>
		res.arrayBuffer(),
	);
	const pdfDoc = await PDFLib.PDFDocument.load(pdfBytes);

	// Convert the data URL to a `Uint8Array`.
	const signatureImageArray = dataURLToUint8Array(signatureDataURL);

	// Embed the signature image as a custom image.
	const signatureImage = await pdfDoc.embedPng(signatureImageArray);
	const { width, height } = signatureImage;

	const pages = pdfDoc.getPages();
	const firstPage = pages[0];

	const x = firstPage.getWidth() - 100 - width; // Adjust the value 100 for the horizontal position.
	const y = firstPage.getHeight() - 100 - height; // Adjust the value 100 for the vertical position.

	// Add the signature image to the first page at the desired location.
	firstPage.drawImage(signatureImage, {
		x: x,
		y: y,
		width: width,
		height: height,
	});

	// Save the modified PDF.
	const modifiedPDFBytes = await pdfDoc.save();
	return modifiedPDFBytes;
}

// Function to convert data URL to a `Uint8Array`.
function dataURLToUint8Array(dataURL) {
	// Extract the Base64-encoded data from the data URL.
	const base64 = dataURL.split(',')[1];

	// Decode the Base64-encoded data into a binary string.
	const binaryString = atob(base64);

	// Create a new `Uint8Array` with the length of the binary string.
	const array = new Uint8Array(binaryString.length);

	// Iterate through the binary string and convert each character to a number and store it in the `Uint8Array`.
	for (let i = 0; i < binaryString.length; i++) {
		array[i] = binaryString.charCodeAt(i);
	}
	return array;
}

The Signature Pad library provides the signature as a data URL in Base64 format. However, the pdf-lib library requires the signature data in Uint8Array format, which is a common method for handling binary data. To insert the signature into the PDF, you need to convert it from Base64 to Uint8Array, which will ensure seamless integration into the document.

Make sure to replace document.pdf with the path to your PDF document.

Step 5 — Triggering the Download of the Modified PDF

Finally, create a function to trigger the download of the modified PDF with the embedded signature. Convert the PDF bytes into a Blob and create a temporary URL for the download:

// Function to trigger the download of the modified PDF.
function downloadModifiedPDF(modifiedPDFBytes) {
	const blob = new Blob([modifiedPDFBytes], {
		type: 'application/pdf',
	});
	const url = URL.createObjectURL(blob);

	// Create a link element to trigger the download.
	const downloadLink = document.createElement('a');
	downloadLink.href = url;
	downloadLink.download = 'modified_document.pdf'; // Specify the filename for the downloaded PDF.

	// Append the link to the body and click it to trigger the download.
	document.body.appendChild(downloadLink);
	downloadLink.click();
	document.body.removeChild(downloadLink);
}

Capturing Signatures in PDFs Using the PSPDFKit for Web JavaScript Library

We at PSPDFKit work on the next generation of PDF viewers for the web. We offer a commercial JavaScript PDF viewer library that can easily be integrated into your web application. PSPDFKit for Web offers 30+ features, enabling users to view, annotate, edit, and sign PDFs directly within the browser.

Requirements

  • Node.js installed on your computer.

  • A code editor of your choice.

  • A package manager compatible with npm.

Adding PSPDFKit to Your Project

  1. Install the pspdfkit package from npm. If you prefer, you can also download PSPDFKit for Web manually:

npm install pspdfkit
  1. For PSPDFKit for Web to work, it’s necessary to copy the directory containing all the required library files (artifacts) to the assets folder. Use the following command to do this:

cp -R ./node_modules/pspdfkit/dist/ ./assets/

Make sure your assets directory contains the pspdfkit.js file and a pspdfkit-lib directory with the library assets.

Integrating into Your Project

  1. Add the PDF document you want to display to your project’s directory. You can use our demo document as an example.

  2. Add an empty <div> element with a defined height to where PSPDFKit will be mounted:

<div id="pspdfkit" style="height: 100vh;"></div>
  1. Include pspdfkit.js in your HTML page:

<script src="assets/pspdfkit.js"></script>
  1. Initialize PSPDFKit for Web in JavaScript by calling PSPDFKit.load():

<script>
	async function loadPSPDFKit() {
	  try {
	    const instance = await PSPDFKit.load({
	      container: '#pspdfkit',
	      document: 'document.pdf',
	    });

	    console.log('PSPDFKit loaded', instance);
	  } catch (error) {
	    console.error(error.message);
	  }
	}

loadPSPDFKit();
</script>

Adding eSignatures via the PSPDFKit UI

In this section, you’ll learn how to sign PDF documents using PSPDFKit’s intuitive UI. First, open the demo and locate the sign icon. Clicking it will prompt a dialog box where you can sign your name. PSPDFKit offers various options to customize your signature, such as selecting the color of your pen and inserting an image or text as your signature. You can also resize and reposition your signature for optimal placement.

In the following sections, you’ll learn how to programmatically add ink and image signatures to PDF documents using JavaScript.

Adding eSignatures Programmatically in JavaScript

PSPDFKit offers two distinct types of signatures that can be added to PDF documents: ink signatures and image signatures. In this section, you’ll learn how to create these signature types programmatically and add them to PDF documents.

Adding Ink Signatures Programmatically

Ink signatures are freehand drawings that resemble traditional pen and paper signatures. To add an ink signature programmatically, modify the PSPDFKit.load() function as follows:

// Create Ink Annotation
const inkAnnotation = new PSPDFKit.Annotations.InkAnnotation({
	pageIndex: 0,
	isSignature: true,
	lines: PSPDFKit.Immutable.List([
		PSPDFKit.Immutable.List([
			new PSPDFKit.Geometry.DrawingPoint({ x: 5, y: 5 }),
			new PSPDFKit.Geometry.DrawingPoint({ x: 95, y: 95 }),
		]),
		PSPDFKit.Immutable.List([
			new PSPDFKit.Geometry.DrawingPoint({ x: 95, y: 5 }),
			new PSPDFKit.Geometry.DrawingPoint({ x: 5, y: 95 }),
		]),
	]),
	boundingBox: new PSPDFKit.Geometry.Rect({
		left: 0,
		top: 0,
		width: 100,
		height: 100,
	}),
});

await instance.create(inkAnnotation);
console.log('Ink annotation created successfully.');

The PSPDFKit.load() function initializes the PSPDFKit instance, and PSPDFKit.Annotations.InkAnnotation creates freehand drawings for ink signatures, with the isSignature property set to true. The lines and boundingBox parameters should remain unchanged, while PSPDFKit.Geometry.DrawingPoint inserts the ink signature, with boundingBox determining its position and size.

Image showing the ink signature

Adding Image Signatures Programmatically

An image annotation allows you to add an image to a PDF document. To add an image signature programmatically, update the PSPDFKit.load() function:

// Create Image Annotation
const request = await fetch('image.png');
const blob = await request.blob();
const attachmentId = await instance.createAttachment(blob);

const imageAnnotation = new PSPDFKit.Annotations.ImageAnnotation({
	pageIndex: 0,
	contentType: 'image/jpeg',
	imageAttachmentId: attachmentId,
	description: 'Image Description',
	boundingBox: new PSPDFKit.Geometry.Rect({
		left: 30,
		top: 20,
		width: 300,
		height: 150,
	}),
});

await instance.create(imageAnnotation);
console.log('Image annotation created successfully.');

In the code snippet, PSPDFKit.Annotations.ImageAnnotation is created by passing several properties — such as pageIndex, contentType, imageAttachmentId, description, and boundingBox — which are defined below:

  • pageIndex — Specifies the page number on which the image annotation is added.

  • isSignature — When an image annotation is created via the signature UI, this flag is set to true.

  • contentType — Specifies the MIME type of the image file.

  • imageAttachmentId — Specifies the ID of the attachment that contains the image data.

  • description — An optional property that provides a description for the image.

  • boundingBox — Specifies the position and size of the image on the PDF document.

Once the image annotation is created, it can be added to the PDF document using the instance.create() method.

To see the image, upload an image file named image.png to the root directory of your project.

Image showing the image annotation

Creating Signature Fields in PDF Documents

With PSPDFKit, you can easily create signature fields in your PDF documents for adding signatures. Update the PSPDFKit.load() function in the index.html file:

// Create Signature Form Field
const widget = new PSPDFKit.Annotations.WidgetAnnotation({
	pageIndex: 0,
	boundingBox: new PSPDFKit.Geometry.Rect({
		left: 200,
		top: 200,
		width: 250,
		height: 150,
	}),
	formFieldName: 'My signature form field',
	id: PSPDFKit.generateInstantId(),
});

const formField = new PSPDFKit.FormFields.SignatureFormField({
	name: 'My signature form field',
	annotationIds: PSPDFKit.Immutable.List([widget.id]),
});

await instance.create([widget, formField]);
console.log('Signature form field created successfully.');

In the code snippet above, you can create a new signature field that allows users to sign within that specific field. The PSPDFKit.Annotations.WidgetAnnotation record is used to define the properties of the signature field, such as its page index, bounding box dimensions, and form field name. The PSPDFKit.FormFields.SignatureFormField record is used to specify the name and IDs of the annotations associated with the signature field. Finally, the instance.create() function is used to create the signature field and add it to the PDF document.

Conclusion

In this tutorial, you first created a simple web app that allows users to capture and save their signatures as images. Additionally, users can insert these signatures into a PDF document, creating a downloadable modified PDF file with the inserted signature.

You then explored how to capture signatures in PDF documents using the PSPDFKit for Web JavaScript library. With PSPDFKit’s comprehensive features, you can efficiently manage electronic signatures and enhance your PDF documents with annotations, text highlighting, and custom forms.

To see a list of all web frameworks, you can contact our Sales team. Or, launch our demo to see our viewer in action.

Author
Hulya Masharipov Technical Writer

Hulya is a frontend web developer and technical writer at Nutrient who enjoys creating responsive, scalable, and maintainable web experiences. She’s passionate about open source, web accessibility, cybersecurity privacy, and blockchain.

Related products
Share post
Free trial Ready to get started?
Free trial