Get your API key
How to add page numbers to a PDF (free, online, no install)

How to add page numbers to a PDF (free, online, no install)

Add page numbers to any PDF in seconds. Free online tool, no upload required. Also covers programmatic methods using Python, Node.js, and pdf-lib.

10 min read

Adding page numbers to a PDF takes under 30 seconds with the right tool. Use the PDF4.dev number PDF tool for an instant browser-based solution: no upload, no install. For programmatic use in Node.js or Python, this article covers working code examples.

The quick way: free online tool

The PDF4.dev number PDF tool adds page numbers client-side in your browser. Your file never leaves your device, which matters when working with confidential documents like contracts or financial reports.

Steps:

  1. Go to pdf4.dev/tools/number-pdf
  2. Drop your PDF onto the upload area
  3. Choose position (bottom center, bottom right, top right, etc.)
  4. Set font size (10px is standard for most documents)
  5. Choose starting number (default: 1)
  6. Click "Add page numbers" and download

The tool works on any modern browser (Chrome, Firefox, Safari, Edge) with no size limit for most documents.

Page number position guide

The position of page numbers affects how professional a document looks and how it behaves when printed.

Use caseRecommended positionFormat
Standard report or articleBottom center1, 2, 3
Double-sided print (book)Bottom outer (alt. left/right)Page X of Y
Legal documentsBottom center or bottom right1, 2, 3
Academic thesisBottom centeri, ii, iii (front matter) then 1, 2, 3
Bates-numbered exhibitsBottom rightPREFIX-000001
Slide deck printed as handoutTop rightPage X of Y

For most general-purpose documents, bottom center at 10-11pt is the safe default.

Add page numbers in Node.js with pdf-lib

pdf-lib is a pure JavaScript library that reads and writes PDF files in Node.js without any native dependencies or Chromium binary.

import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
import { readFileSync, writeFileSync } from "fs";
 
async function addPageNumbers(inputPath: string, outputPath: string) {
  const existingPdfBytes = readFileSync(inputPath);
  const pdfDoc = await PDFDocument.load(existingPdfBytes);
  const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
  const pages = pdfDoc.getPages();
  const totalPages = pages.length;
 
  pages.forEach((page, index) => {
    const { width, height } = page.getSize();
    const pageNumber = index + 1;
    const text = `${pageNumber} / ${totalPages}`;
    const fontSize = 10;
    const textWidth = font.widthOfTextAtSize(text, fontSize);
 
    page.drawText(text, {
      x: (width - textWidth) / 2, // centered horizontally
      y: 20,                       // 20pt from bottom
      size: fontSize,
      font,
      color: rgb(0.4, 0.4, 0.4),  // gray
    });
  });
 
  const pdfBytes = await pdfDoc.save();
  writeFileSync(outputPath, pdfBytes);
  console.log(`Added page numbers to ${totalPages} pages → ${outputPath}`);
}
 
addPageNumbers("input.pdf", "output-numbered.pdf");

Install pdf-lib with:

npm install pdf-lib

The library is pure JavaScript, no native addons, no Chromium. It works in Node.js, browsers, Deno, and any JavaScript runtime.

Add page numbers in Python

Python has two common approaches: pypdf for reading existing PDFs and overlaying text, or reportlab for generating PDFs with page numbers from scratch.

import io
from pypdf import PdfReader, PdfWriter
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
 
def add_page_numbers(input_path: str, output_path: str) -> None:
    reader = PdfReader(input_path)
    writer = PdfWriter()
    total_pages = len(reader.pages)
 
    for i, page in enumerate(reader.pages):
        # Get page dimensions
        width = float(page.mediabox.width)
        height = float(page.mediabox.height)
 
        # Create an overlay PDF with just the page number
        packet = io.BytesIO()
        c = canvas.Canvas(packet, pagesize=(width, height))
        c.setFont("Helvetica", 10)
        c.setFillColorRGB(0.4, 0.4, 0.4)
 
        text = f"{i + 1} / {total_pages}"
        text_width = c.stringWidth(text, "Helvetica", 10)
        c.drawString((width - text_width) / 2, 20, text)
        c.save()
 
        # Merge the overlay onto the existing page
        packet.seek(0)
        overlay_pdf = PdfReader(packet)
        page.merge_page(overlay_pdf.pages[0])
        writer.add_page(page)
 
    with open(output_path, "wb") as f:
        writer.write(f)
 
    print(f"Added page numbers to {total_pages} pages → {output_path}")
 
add_page_numbers("input.pdf", "output-numbered.pdf")

Install dependencies:

# pypdf + reportlab approach
pip install pypdf reportlab
 
# PyMuPDF approach (faster, simpler API)
pip install pymupdf

PyMuPDF (also known as fitz) is typically faster than the pypdf+reportlab combination because it reads and writes the PDF content stream directly without creating intermediate overlay documents.

Skip numbering for the first N pages

A common requirement: skip the cover page and table of contents, then start numbering at page 1 for the body content.

// TypeScript — skip first 2 pages, start body at page "1"
pages.forEach((page, index) => {
  const skipPages = 2; // cover + table of contents
  if (index < skipPages) return; // no number on these pages
 
  const { width } = page.getSize();
  const displayNumber = index - skipPages + 1; // page 3 of doc = "1"
  const text = `${displayNumber}`;
  const textWidth = font.widthOfTextAtSize(text, fontSize);
 
  page.drawText(text, {
    x: (width - textWidth) / 2,
    y: 20,
    size: fontSize,
    font,
    color: rgb(0.4, 0.4, 0.4),
  });
});

This is sometimes called an "offset" or "starting number" feature. Many online tools support it via a "Start numbering from page N" option.

Number format options

Different documents call for different number formats. Here are the most common:

FormatExampleWhen to use
Plain number3Minimal, slides, short reports
Page X of YPage 3 of 47Long documents, formal reports
Centered dash- 3 -Book chapters, academic papers
Roman numeralsiiiFront matter (intro, TOC)
Bates numberEXHIBIT-000003Legal, litigation, compliance
Section prefix2-3Multi-section technical docs

For Roman numeral conversion in JavaScript:

function toRoman(num: number): string {
  const values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
  const symbols = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"];
  let result = "";
  for (let i = 0; i < values.length; i++) {
    while (num >= values[i]) {
      result += symbols[i];
      num -= values[i];
    }
  }
  return result.toLowerCase(); // "iii" instead of "III"
}

Add page numbers when generating PDFs from HTML

If you generate PDFs from HTML using the PDF4.dev API or a similar HTML-to-PDF service, add page numbers directly in the HTML/CSS using CSS paged media. This is the cleanest approach because the numbering is part of the document design, not a post-processing step.

<!DOCTYPE html>
<html>
<head>
<style>
  @page {
    margin: 20mm 15mm 25mm 15mm;
 
    @bottom-center {
      content: counter(page) " / " counter(pages);
      font-family: Helvetica, sans-serif;
      font-size: 10pt;
      color: #666;
    }
  }
 
  body {
    font-family: Helvetica, sans-serif;
  }
</style>
</head>
<body>
  <h1>My Report</h1>
  <p>Page numbers appear automatically in the footer.</p>
</body>
</html>

The counter(page) and counter(pages) CSS values are standard in the CSS Paged Media spec. Chromium-based PDF renderers (including the one PDF4.dev uses) support them natively.

For more CSS print techniques, see the CSS print styles guide.

Adding page numbers via the PDF4.dev REST API

If you need to generate numbered PDFs at scale, use the PDF4.dev API. Include the CSS @page counter technique above in your HTML template, then call the API with your dynamic data.

const response = await fetch("https://api.pdf4.dev/v1/render", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PDF4_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    html: myHtmlTemplate, // includes @page { @bottom-center { content: counter(page) } }
    data: { title: "Q1 Report", sections: reportData },
  }),
});
 
const pdfBuffer = await response.arrayBuffer();

This approach generates the numbered PDF in a single API call. No post-processing step, no second library to install. See the Node.js PDF generation guide for a complete working example.

When post-processing is the right approach

Use a post-processing library (pdf-lib, PyMuPDF) when:

  • You receive pre-existing PDFs from a third-party (scanned documents, uploaded files)
  • The numbering requirement is an afterthought and you cannot change the original generation pipeline
  • You need to add Bates numbers to a batch of unrelated documents for legal purposes

Use CSS @page counters or in-template numbering when:

  • You control the HTML that generates the PDF
  • The page number style needs to match the document design closely
  • You want a single-step pipeline with no additional dependencies

Batch processing: number multiple PDFs

To number hundreds of PDFs in a folder, loop over the files in Node.js:

import { readdirSync } from "fs";
import path from "path";
 
const inputDir = "./pdfs";
const outputDir = "./pdfs-numbered";
 
const files = readdirSync(inputDir).filter((f) => f.endsWith(".pdf"));
 
for (const file of files) {
  await addPageNumbers(
    path.join(inputDir, file),
    path.join(outputDir, file)
  );
  console.log(`Numbered: ${file}`);
}

For parallel processing across a large batch, use Promise.all with a concurrency limit:

import pLimit from "p-limit"; // npm install p-limit
 
const limit = pLimit(4); // 4 concurrent operations
 
await Promise.all(
  files.map((file) =>
    limit(() =>
      addPageNumbers(
        path.join(inputDir, file),
        path.join(outputDir, file)
      )
    )
  )
);

Common issues

Page numbers appear on the wrong side when printed double-sided. Use alternating positions: bottom-right on odd pages, bottom-left on even pages. In pdf-lib, check index % 2 === 0 to determine left or right alignment.

Page numbers overlap existing content. Increase the bottom page margin before generating the PDF, or lower the Y position of the number stamp (e.g., from y: 20 to y: 10). If working with a pre-existing PDF you cannot regenerate, you may need to set a crop box or add a white rectangle behind the number.

Roman numerals needed for front matter only. Split the PDF by section, apply Roman numerals to the first N pages and Arabic numerals to the rest, then merge the sections back together.

Numbers appear blurry or pixelated. This happens when the PDF is treated as a raster image internally. Ensure you are using vector text operations (pdf-lib drawText, PyMuPDF insert_text) rather than rasterizing the page first.

Tools at a glance

ApproachEffortBest for
PDF4.dev number-pdf toolZeroQuick one-off, any document
CSS @page counterLowNew PDFs generated from HTML
pdf-lib (Node.js)MediumBatch automation, existing PDFs
PyMuPDF (Python)MediumPython workflows, large batches
pdf-lib + reportlabMedium-highPython, complex overlay needs

For most developers generating PDFs from scratch, CSS @page counters are the cleanest solution. For modifying existing PDFs, pdf-lib (Node.js) or PyMuPDF (Python) are the fastest options to add to an existing pipeline.

Once you have page numbers sorted, the next common task is reordering pages or splitting the document into sections.

Free tools mentioned:

Number PdfTry it freeMerge PdfTry it freeReorder PdfTry it freeSplit PdfTry it free

Frequently asked questions

How do I add page numbers to a PDF for free?
Use the PDF4.dev number PDF tool at pdf4.dev/tools/number-pdf. Upload your file, choose position (bottom center, top right, etc.), font size, and starting page number. The tool runs in your browser: your file is never uploaded to a server.
Can I add page numbers to a PDF without Adobe Acrobat?
Yes. PDF4.dev's free online tool adds page numbers without any software install. It runs client-side in your browser using pdf-lib, so you do not need Acrobat, Word, or any desktop app.
How do I start page numbering from a specific page?
Most tools let you set a starting page offset. For example, if your document has a cover page and a table of contents on pages 1-2, you can start numbering from page 3 but display '1' as the first number. The PDF4.dev number-pdf tool supports this with a 'start from page' option.
Can I add page numbers to only some pages of a PDF?
Programmatically, yes: use pdf-lib or PyPDF2 to iterate over a specific page range and add numbers only to those pages. The free online tool adds numbers to all pages, which covers the most common use case.
How do I add page numbers to a PDF in Python?
Use the reportlab or pdf-lib libraries. The most reliable approach is to use PyPDF2 to read the existing PDF and add text annotations page by page, or use pdf-lib via a Node.js script. See the code examples in this article for working implementations.
What is Bates numbering and how is it different from page numbering?
Bates numbering is a legal stamping system where each page gets a unique sequential identifier, often with a prefix (e.g., DOC-000001). It is used in litigation to track documents across large sets. Regular page numbering (1, 2, 3...) is for reader navigation. Both can be added with the same technical approach.
Does adding page numbers change the PDF file size?
Slightly. Each page number is a small text annotation added to the PDF content stream. For a 100-page document, the size increase is typically under 50KB, negligible compared to the document content.
Can I customize the format of page numbers in a PDF?
Yes. Common formats include: plain number (1, 2, 3), 'Page X of Y', Roman numerals (i, ii, iii), or custom prefixes (A-1, A-2). Programmatic approaches with pdf-lib or PyPDF2 support any format you can format as a string.
Where should page numbers be positioned in a PDF?
Bottom center is the most common position for single-sided documents. For documents that will be printed double-sided (books, reports), use alternating positions: bottom-right on odd pages, bottom-left on even pages. Headers work well for legal documents.
Can I remove or change page numbers already in a PDF?
If the page numbers were added as annotations or content overlays, some tools can remove them. If they were baked into the original page content (as static text), removing them requires editing the PDF content stream, which is complex. The easiest solution is often to regenerate the PDF from the source document.

Start generating PDFs

Build PDF templates with a visual editor. Render them via API from any language in ~300ms.