BASALT · JOURNAL

Bates numbering on a Mac without Acrobat

2026-08-06 · bates numbering mac

Bates numbering is a sequential unique identifier stamped on every page of a production so that any page can be cited without ambiguity. It sounds like a formatting task. It is closer to assigning primary keys, and the failure modes are the ones you would expect from a database with no uniqueness constraint.

macOS ships nothing that does it. Preview cannot, Automator's PDF actions cannot, and Quartz filters operate on rendering, not on stamping sequences. Here is what the job actually requires and how to do it on a Mac.

What the number has to guarantee

Three properties, and every rule below follows from them.

Unique. No number appears on two pages, ever, across the whole matter. Not just within a volume. If you produce volume one ending at ABC000450, volume two starts at ABC000451.

Sequential and gapless. The receiving party uses continuity to know they have everything. A gap reads as a withheld page, which is fine only if that is what you meant and it is on the privilege log. Accidental gaps generate correspondence.

Permanent. The number must survive downstream handling: copying, printing, re-saving, extracting a page range. A citation to ABC000112 has to resolve to the same page a year later.

Everything else, the prefix, the padding width, the corner it sits in, is convention. Useful convention, but convention.

Format conventions worth following

A prefix identifying the producing party, usually two to five letters, then a zero-padded number. SMITH000001. Pick the padding width from the expected size of the whole production and add a digit. Six digits handles a million pages and costs nothing; four digits looks tidy until the production hits 10,000 pages and you have to choose between an inconsistent format and a renumber.

Place the number in the bottom-right margin. It is the conventional position and, more practically, it is the least likely corner to collide with content. If a page has content to the edge, move the stamp for the whole production, not for that page, so the position stays predictable.

Keep confidentiality designations separate from the Bates number. A protective order designation can change during a matter; the Bates number cannot. Stamping "CONFIDENTIAL" as part of the same string forces a renumber if the designation is later withdrawn.

The page geometry traps

This is where naive stamping scripts go wrong, and the failures are visible only after you have stamped a few thousand pages.

MediaBox origin is not always (0, 0). The spec allows any rectangle. A page whose MediaBox is [0 0 612 792] and one whose MediaBox is [-12 -12 600 780] describe pages of the same size in different coordinate frames. A stamp drawn at a fixed offset from the origin lands in a different place on each.

CropBox governs what is displayed. If a page has a CropBox smaller than its MediaBox, the visible page is the CropBox. Compute the stamp position from the CropBox, falling back to the MediaBox when there is no CropBox, or your numbers will drift off the visible page on cropped pages.

/Rotate rotates the rendered page, not the coordinate system. A page with /Rotate 90 displays sideways relative to its content coordinates. A stamp placed at the bottom-right of the content space appears in a different corner, rotated, in the viewer. You have to apply the inverse rotation to the stamp's transformation matrix so the number reads horizontally in the corner the reader sees.

Page sizes vary within a document. Productions mix letter, legal, A4, and scanned pages of odd dimensions. Any position hardcoded in points rather than computed per page will be wrong on some of them.

Existing content state. Appending drawing operators to an existing content stream inherits whatever graphics state that stream ended in: a clipping path, a non-default color, a transformation matrix. Wrap the stamp in q and Q to save and restore the graphics state, and reset the matrix explicitly, or your number may be clipped away, invisible, or drawn at a strange scale.

Content stream, not annotation

You can put text on a page two ways: append operators to the page content stream, or add a free text annotation.

Use the content stream. An annotation is a separate object that any PDF editor can delete in one action, that may or may not print depending on its flags, and that some processing pipelines strip wholesale. A Bates number that a downstream tool can silently remove violates the permanence property.

If you also want the number to survive text extraction, so a receiving party can search for ABC000112 and land on the right page, it has to be real text with a font resource and a ToUnicode mapping, not a path-drawn outline or a rasterized image of the number.

Doing it with command line tools

There is no single Mac tool for this, so the common approach is to generate an overlay and merge it.

Generate a one-page-per-page overlay PDF where each page contains only the number, positioned correctly, then merge it onto the source. pdftk-java calls this multistamp:

pdftk-java source.pdf multistamp overlay.pdf output numbered.pdf

The overlay itself is where the work is. A Python script using pypdf to read each page's CropBox and /Rotate, and reportlab to draw the corresponding overlay page at the right size and offset, is maybe eighty lines. That script has to handle the geometry cases above; if it does not, it works on your test file and fails on the production.

For a production spanning multiple documents, the counter has to persist across files in the order the documents will be produced, which means the script drives the whole set, not one file at a time. Sorting matters: a naive directory listing sorts doc10.pdf before doc2.pdf, and a production numbered in that order is technically valid and practically confusing.

After stamping, verify: extract the text of every page, pull the Bates string, and assert that the sequence increments by exactly one with no repeats. That check takes a few lines and catches a mis-sorted set, a restarted counter, and a page that failed to receive a stamp.

Order relative to redaction

Endorse before you redact.

The privilege log has to point at Bates ranges, and a redaction log generated from marks placed on already-endorsed pages is consistent by construction. Endorse afterward and you have two independent passes whose agreement is assumed rather than enforced. This ordering is part of the broader sequence in a redaction workflow for law firms, and it is what makes building a privilege log from the redactions you already made possible.

One consequence to plan for: because the number is applied first, a redaction tool that rewrites the page content must preserve the stamp. That is normal if the redaction only removes the glyph runs intersecting a mark, since the stamp sits in the margin. It is not normal if the tool rasterizes and re-emits pages, which can degrade the number's searchability.

Frequently asked questions

How do I add Bates numbers on a Mac?

macOS has no built-in Bates numbering, so you need either a dedicated PDF application or a script that generates a positioned overlay and merges it with a tool like pdftk-java multistamp. The overlay must be computed per page from the CropBox and /Rotate value, not from a fixed offset. Stamp into the page content stream rather than as an annotation so the number cannot be deleted downstream.

Can Preview add Bates numbers?

No. Preview has no page numbering or stamping feature, and its markup tools place annotations rather than sequential identifiers written into the page content. Automator's PDF actions and Quartz filters do not do it either, since they operate on rendering and page assembly rather than on maintaining a counter across a production.

What is a Bates number?

A Bates number is a sequential unique identifier stamped on every page of a document production so that any page can be cited unambiguously. It is conventionally a party prefix followed by a zero-padded number, such as SMITH000001, placed in the bottom-right margin. Its three requirements are uniqueness across the entire matter, gapless sequence, and permanence through downstream handling.

Should I Bates stamp before or after redacting?

Before. The privilege log references Bates ranges, so placing marks on pages that already carry their permanent identifier makes the log consistent with the production by construction. Stamping after redaction creates two independent passes whose agreement is assumed rather than enforced, which is where mismatches between the log and the file appear.

How many digits should a Bates number have?

Pick the width from the expected size of the whole production and add a digit, which in practice means six for most matters. Six digits covers a million pages and costs nothing in width, whereas four digits forces a choice between an inconsistent format and a full renumber the moment the production passes ten thousand pages. The width must stay fixed for the entire matter.

Do Bates numbers need to continue across volumes?

Yes. Uniqueness is across the whole matter, not within a file or a volume, so if volume one ends at ABC000450 then volume two begins at ABC000451. Restarting the counter per document produces duplicate identifiers, which defeats the purpose of the number and generates correspondence with the receiving party.

Why are my page numbers landing in the wrong corner?

Almost always /Rotate or a non-zero CropBox origin. A /Rotate 90 page displays sideways relative to its content coordinates, so a stamp placed at the bottom-right of content space appears elsewhere and rotated in the viewer, and a CropBox smaller than the MediaBox moves the visible page relative to the coordinate origin. Compute the position from the CropBox and apply the inverse rotation.

How do I check a Bates sequence is correct?

Extract the text of every page, pull the Bates string from each, and assert the sequence increments by exactly one with no repeats and no gaps. That check catches a mis-sorted document set, a counter that restarted mid-production, and any page that silently failed to receive a stamp. Run it on the produced files, not on the working copies.

Doing it in Basalt

Basalt applies sequential Bates numbers across a whole production with a prefix and a starting number, computing each page's position from its own geometry so rotated and cropped pages come out right. Because the numbering, redaction, and privilege log tools live in the same window, you can endorse first, mark with reasons, then export a log keyed to the numbers you already applied. Redaction preserves the endorsement, removes text from the content stream rather than covering it, and a built-in verifier proves the result before any file is written. It is one of 18 tools in the app, $29 once for up to three Macs, free for 24 hours, at basaltformac.com.

Redaction that proves itself

Basalt destroys the content you mark, then re-opens the file it wrote and proves the content is gone before it saves anything. Your documents never leave your Mac.

DOWNLOAD BASALT 2.3.0 BUY $29 FREE FOR 24 HOURS · MACOS 13+