pdf-lib Watermark and Page Numbers for Existing PDFs — Free Snippet

pdf-lib Watermark and Page Numbers for Existing PDFs · Tools · Plain HTML, CSS & JS · Live preview

What's included

Features

Stamps existing PDFs
Load, draw on each page, save.
Rotated watermark
Any angle from −90° to 90°.
Correct rotated centring
Start point offset by the rotated half-size.
Adjustable opacity
Content underneath stays readable.
Colour picker
Hex converted to pdf-lib rgb().
Page X of N footers
Centred or right-aligned.
Non-destructive re-stamping
Always starts from the original bytes.
Live page previews
Up to six pages rendered with PDF.js.

About this UI Snippet

Watermarking PDFs With pdf-lib — Rotated Text, Opacity and Page Numbers

Screenshot of the pdf-lib Watermark and Page Numbers for Existing PDFs snippet rendered live

Stamping "DRAFT" or "CONFIDENTIAL" across every page, or adding page numbers to a document that doesn't have them, are everyday PDF chores. pdf-lib can modify an existing PDF in the browser: load it, draw on top of each page, save. This snippet adds a configurable watermark and footer and shows the stamped pages live.

Editing, not re-creating

PDFDocument.load(bytes) parses the existing file, and getPages() returns its pages. Drawing with page.drawText adds new content on top of what's already there — text, images and vector content in the original are untouched, and text stays selectable.

Always stamp from the original

Each change of text, size, angle or colour reloads the *original* bytes and stamps again. Stamping the previous output instead would layer watermark upon watermark every time a slider moved.

Centring rotated text is geometry

drawText with rotate: degrees(a) rotates around the text's start point — the left end of its baseline — not its centre. Putting that point at the page centre would swing the text off to one side. The snippet measures the text with widthOfTextAtSize and heightAtSize, then moves the start point back from the centre by half the width and half the height rotated by the same angle, so the watermark's midpoint lands exactly in the middle at any angle.

Transparency and colour

opacity makes the watermark translucent so the content underneath stays readable. The colour picker's hex value converts to pdf-lib's rgb(), which takes 0–1 components.

Page numbers

"Page X of N" is measured and either centred or right-aligned 40 points from the edge, 26 points above the bottom.

Private by default

Files are read with the File API and never uploaded. A generated three-page sample means the tool works without your own file.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet into an AI assistant like Claude and ask it to derive the rotated-text centring formula with a diagram. Ask it to add an image watermark (a logo PNG with embedPng), a tiled diagonal pattern across the page, a watermark applied only to selected pages, or a header with the document title and date. It can also help you keep file size low when stamping large documents.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a browser-based PDF watermark and page-number tool with pdf-lib and a PDF.js 3 preview (both from a CDN) in plain HTML, CSS and JavaScript.

Requirements:
- Start with a generated three-page sample PDF, and let the user choose their own PDF file, validating it before use.
- Controls for watermark text, font size, angle (−90 to 90), opacity and colour, plus a page-number toggle with centred or right-aligned position.
- On every change, reload the original bytes (never the previous output), embed Helvetica Bold, and draw the watermark on every page centred at the page midpoint accounting for rotation: offset the start point by half the text width and height rotated by the angle.
- Draw "Page X of N" footers, measured for alignment.
- Render up to six stamped pages with PDF.js (passing a copy of the bytes), ignore outdated renders, and show page count and size.
- A download button that saves stamped.pdf via a Blob URL with a note about sandboxed previews.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="pw">
  <aside class="pw-panel">
    <h2>Stamp a PDF</h2>
    <label class="pw-file">Choose a PDF <input type="file" id="pwFile" accept="application/pdf"></label>
    <p class="pw-src" id="pwSrc">Using a generated 3-page sample.</p>
    <fieldset>
      <legend>Watermark</legend>
      <label>Text <input id="pwText" value="CONFIDENTIAL" maxlength="24"></label>
      <label>Size <input type="range" id="pwSize" min="24" max="110" value="64"></label>
      <label>Angle <input type="range" id="pwAngle" min="-90" max="90" value="35"></label>
      <label>Opacity <input type="range" id="pwOpacity" min="5" max="60" value="18"></label>
      <label>Colour <input type="color" id="pwColor" value="#dc2626"></label>
    </fieldset>
    <fieldset>
      <legend>Footer</legend>
      <label class="pw-check"><input type="checkbox" id="pwNums" checked> Page numbers "Page X of N"</label>
      <label>Position <select id="pwPos"><option value="center">Centre</option><option value="right">Right</option></select></label>
    </fieldset>
    <button type="button" id="pwDownload">Download stamped PDF</button>
    <p class="pw-status" id="pwStatus" role="status"></p>
  </aside>
  <div class="pw-preview" id="pwPages" aria-label="Preview of stamped pages"></div>
</div>

Step by step

How to Use

  1. 1
    Start with the sampleA generated 3-page report is stamped immediately.
  2. 2
    Adjust the watermarkText, size, angle, opacity and colour update the preview.
  3. 3
    Toggle page numbersCentred or right-aligned "Page X of N".
  4. 4
    Use your own PDFChoose a file; it's processed locally.
  5. 5
    DownloadSaves stamped.pdf (open in its own tab if the sandbox blocks it).

Real-world uses

Common Use Cases

Drafts and reviews
Mark documents as DRAFT before sharing.
Confidential sharing
Label sensitive reports.
Adding page numbers
Fix documents exported without them.
Education
Stamp "SAMPLE" on handouts.
Internal tools
Batch stamping without a server.
Related: pdf-lib Merge PDFs
Related: jsPDF Invoice Generator
Create PDFs from scratch instead: jsPDF Invoice Generator with Live PDF Preview.

Got questions?

Frequently Asked Questions

Load the file with pdf-lib's PDFDocument.load, embed a font, and for each page call page.drawText with the watermark text, a rotate value from degrees(), a colour and an opacity. Save the document to get the stamped bytes.

drawText rotates around the text's start point. Measure the text width and height, then place the start point at the page centre minus half the width and height rotated by the angle: x = cx − (w/2)cosθ + (h/2)sinθ and y = cy − (w/2)sinθ − (h/2)cosθ.

Yes. Loop over doc.getPages() and draw "Page i of n" on each, measuring the label with font.widthOfTextAtSize to centre or right-align it.

No. A watermark is visible labelling, not protection; someone can remove or crop it. Use it to communicate status or ownership, not as security.

Drawing adds content permanently to the loaded document. Re-stamping the previous output would add another watermark each time, so the snippet always starts from the untouched source bytes.