Practical guidesCounting

Count pages in a folder of PDFs without hiding failures

Use a read-only local Python example to count PDF pages, export a CSV ledger and keep encrypted or failed files separate from confirmed totals.

At a glance

For local files, count each readable PDF into a ledger with a filename, count and result. Sum confirmed numeric counts only and report the number of unresolved files separately. A folder count does not discover website links or automatically deduplicate files with different names.

Worked exampleIllustrative data

The confirmed total is 28 pages plus one unresolved file, not 28 pages for the complete folder.

Example local result
FilePagesResult
letter.pdf4counted
report.pdf24counted
protected.pdfencrypted

Scroll sideways to see all columns. Use arrow keys when the table is focused.

Work on a trusted, bounded folder

Make a separate working folder of PDFs you are authorized to inspect. The example reads files and writes a new CSV; it does not rewrite any source. Install pypdf in a local Python environment, record its version and keep the file list fixed while comparing results.

This short example is intended for trusted local files. It has no malware service, process isolation or time/memory limits and is not a production ingestion service. For an untrusted or very large collection, use a maintained isolated processing workflow with explicit resource limits.

Write a result for every file

Strict reading makes structural problems visible. Encrypted files are deliberately left unresolved; handle any authorized password through a separate secure workflow. A parser result should not be described as independent verification or accessibility validation.

The CSV keeps an empty count for failures and a fixed result label. When importing filenames into a spreadsheet, prefix names that begin with a spreadsheet-formula character so the sheet treats them as text.

Python example · Trusted local files only
from pathlib import Path
import csv
from pypdf import PdfReader

def safe_name(value):
    risky = value.lstrip().startswith(('=', '+', '-', '@'))
    return "'" + value if risky else value

with open('pdf-page-counts.csv', 'w', newline='', encoding='utf-8-sig') as out:
    writer = csv.writer(out)
    writer.writerow(['file', 'pages', 'result'])
    files = (path for path in Path('pdfs').iterdir()
             if path.is_file() and path.suffix.lower() == '.pdf')
    for path in sorted(files):
        pages, result = '', 'unreadable_or_invalid'
        try:
            with path.open('rb') as source:
                reader = PdfReader(source, strict=True)
                if reader.is_encrypted:
                    result = 'encrypted'
                else:
                    count = len(reader.pages)
                    if count > 0:
                        pages, result = count, 'counted'
        except Exception:
            pass  # Keep an unresolved row; never substitute zero.
        writer.writerow([safe_name(path.name), pages, result])

Check the ledger before using the total

Open several ordinary files in a viewer and compare their counts with the CSV. Investigate every unresolved row with the owner; do not remove it from the collection simply because it is inconvenient to count. Warning, encrypted and malformed states may need different tools or a fresh source export.

If duplicate handling matters, add a byte-digest column and a clearly documented grouping rule before totaling unique pages. If you instead sum every counted row, label the measure pages across local files. Keep the script, parser version, file-list date and unresolved count with the reported number.

  1. Inspect the CSV’s result column.
  2. Sum only counted rows.
  3. Show unresolved files beside the total.
  4. Preserve a dated ledger and document any duplicate rule.

Sources and scope

Methods, worksheets and illustrative examples are DocAccessible editorial contributions. These references support the technical or product details described above. W3C techniques are informative guidance; they are not a certification scheme.

  1. QPDF: PDF inspection and exit status

    Structural inspection, page-count options and warning versus error outcomes.

  2. pypdf: reading PDF files

    Encrypted-reader behavior and the need for an authorized password.

  3. Python hashlib documentation

    SHA-256 hashing of file bytes.

Written by the DocAccessible team under our editorial policy. Suggest a correction if a source or product detail needs updating.

See the evidence in a working example

Explore the public sample inventory report to try its table, full-screen view and missing-count reasons. The downloadable counting fixture check records what the local counter returned for seven self-authored inputs, with hashes and explicit limits.

Put the method to work.

Start with a clearer picture of your PDFs.

Need website-wide counting instead?