PDF Merger and Splitter in Python: Avoid Limitations and Website Privacy Risks

   

How many times have you needed to merge two PDF documents or extract a few specific pages and resorted to the first free website found on Google?

While these services are convenient, they bring along two major issues:

  1. Privacy and Security: You are uploading potentially confidential documents (invoices, contracts, personal data) to third-party servers whose data management policies you often don't know.
  2. Operational limits: Maximum file size, limited number of daily operations, or annoying ad banners.

The solution? Build your own local Python utility. Not only is it incredibly simple to create, but it works instantly, is 100% secure, and imposes no limits.

🔗 Do you like Techelopment? Check out the website for all the details!

The Ingredients: Why we use pypdf

For this project, we use pypdf (the modern, actively maintained successor to the historic PyPDF2 library). It is a lightweight, fast, pure-Python library that is super easy to integrate.

To install it, open your terminal and run:

pip install pypdf

Script Architecture

Our script covers two main needs:

  • Merging (Merge): Scans a target folder, finds all .pdf files, and merges them into a single alphabetically sorted document.
  • Extraction (Split/Extract): Takes a PDF file and generates a new document keeping only the desired page range (e.g., from page 2 to 5).

We structured the code both as a reusable module and with a guided, interactive Command Line Interface (CLI).


The Complete Code

Here is the complete source code ready to use. Save it as pdf_merger_splitter.py:

import os
from pathlib import Path
from pypdf import PdfReader, PdfWriter


def merge_pdfs(input_folder: str, output_file: str) -> None:
    """Merges all PDF files in the specified folder into a single file."""
    input_folder = input_folder.strip().strip('"').strip("'")
    folder_path = Path(input_folder)

    if not folder_path.exists() or not folder_path.is_dir():
        print(f"❌ Error: The folder '{input_folder}' does not exist.")
        return

    # Retrieve and sort all .pdf files in the folder
    pdf_files = sorted([f for f in folder_path.glob("*.pdf")])

    if not pdf_files:
        print(f"⚠️ No PDF files found in '{input_folder}'.")
        return

    merger = PdfWriter()

    print(f"🔍 Found {len(pdf_files)} PDF files. Starting merge...")
    for pdf in pdf_files:
        print(f"  └─ Adding: {pdf.name}")
        merger.append(str(pdf))

    output_file = output_file.strip().strip('"').strip("'")
    merger.write(output_file)
    merger.close()
    print(f"✅ Merge completed successfully! Saved to: {output_file}\n")


def extract_pages(
    input_file: str, output_file: str, start_page: int, end_page: int
) -> None:
    """Extracts a specific range of pages (1-based) from a PDF and saves them to a new file."""
    input_file = input_file.strip().strip('"').strip("'")
    file_path = Path(input_file)

    if not file_path.exists():
        print(f"❌ Error: The file '{input_file}' does not exist.")
        return

    reader = PdfReader(file_path)
    writer = PdfWriter()
    total_pages = len(reader.pages)

    # Range validation
    if start_page < 1 or end_page > total_pages or start_page > end_page:
        print(
            f"❌ Error: Invalid range. The document contains {total_pages} pages."
        )
        return

    # pypdf uses 0-based indexing, convert from 1-based
    for idx in range(start_page - 1, end_page):
        writer.add_page(reader.pages[idx])

    output_file = output_file.strip().strip('"').strip("'")
    with open(output_file, "wb") as f_out:
        writer.write(f_out)

    print(
        f"✅ Pages from {start_page} to {end_page} successfully extracted!"
    )
    print(f"📂 Saved to: {output_file}\n")


def main():
    print("=" * 50)
    print(" 📄 PDF MANAGEMENT UTILITY (Local & Private)")
    print("=" * 50)
    print("1. Merge all PDFs (alphabetically) in a folder")
    print("2. Extract page range from a PDF")
    print("3. Exit")

    choice = input("\nSelect an option (1-3): ").strip()

    if choice == "1":
        folder = input("Path to the folder containing PDFs: [Drag & drop folder here to save time]").strip()
        output = input(
            "Output file name (e.g. merged.pdf) [Default: merged.pdf]: "
        ).strip()
        if not output:
            output = "merged.pdf"
        merge_pdfs(folder, output)

    elif choice == "2":
        file_in = input("Path to the source PDF file: [Drag & drop file here to save time]").strip()
        file_out = input(
            "Output file name [Default: extracted.pdf]: "
        ).strip()
        if not file_out:
            file_out = "extracted.pdf"

        try:
            p_start = int(input("Start page (from 1): "))
            p_end = int(input("End page: "))
            extract_pages(file_in, file_out, p_start, p_end)
        except ValueError:
            print("❌ Error: Please enter valid integer numbers for pages.")

    elif choice == "3":
        print("Goodbye!")
    else:
        print("Invalid option.")


if __name__ == "__main__":
    main()

How to Use It

  1. Run the script: Open the terminal in the folder where the script is located and execute:
    python pdf_merger_splitter.py
  2. To merge multiple PDFs: Enter the folder where the files are located. The script will read them in alphabetical order and generate the combined file.
  3. To extract pages: Specify the source file and indicate the range (e.g., from page 1 to 3).

📍 Where is the final file saved?

It depends on how you type the output file name:
  • Simple name (e.g. merged.pdf): The file will be saved in the same folder where you are running the Python script (the current working directory of the terminal).
  • Full path (e.g. C:\Users\John\Desktop\merged.pdf or /Users/john/Desktop/merged.pdf): The file will be generated exactly in the specified destination folder.

Practical Guide to Paths: How to never make a mistake

File paths have always been the main obstacle when using command-line tools. A small typo or a wrong space is enough to make the script fail.

Here is a practical guide with the easiest methods to specify paths without hassle, on both Windows and Mac.

💡 The Ultimate Trick: Drag & Drop

No need to type the path manually. When the script asks you:
Path to the folder... or Path to the source PDF file...

  1. Open the folder or file in your File Explorer (Windows) or Finder (Mac).
  2. Drag and drop it directly into the Terminal window.
  3. The terminal will automatically write the complete and correct path for you!
  4. Press Enter.

🛠️ How to get the path manually

If you prefer to copy and paste it, here is how to do it on different systems:

🪟 On Windows

  1. Select the file or folder.
  2. Press the key combination Ctrl + Shift + C (Copy as path).
    • Alternatively: Right-click the file/folder and select "Copy as path".
  3. Paste into the terminal with Ctrl + V.

Note for Windows: If the path contains quotation marks (e.g., "C:\My Documents\file.pdf"), you can leave them or remove them: the Python script or shell will handle them seamlessly.

🍎 On Mac

  1. Right-click (or two-finger tap on the trackpad) the file or folder.
  2. Hold down the Option (⌥) key on your keyboard.
  3. The menu item "Copy [Name] as Pathname" will appear.
  4. Paste into the terminal with Cmd + V.

📌 Practical Syntax Examples

Paths can be written in two ways: Absolute (starting from the drive root) or Relative (starting from where you currently are).

1. Absolute Paths (Recommended to avoid errors)

They point to the exact location on the computer, regardless of where the Python script is saved.

  • Windows:
    • File: C:\Users\John\Desktop\invoice.pdf
    • Folder: C:\Users\John\Documents\PDFs_To_Merge
  • Mac / Linux:
    • File: /Users/john/Desktop/invoice.pdf
    • Folder: /Users/john/Documents/PDFs_To_Merge

2. Paths with Spaces

If the folder or file contains spaces (e.g., My Documents), make sure to enclose the path in quotation marks if typing manually, or simply use the Drag & Drop method mentioned above, which handles spaces automatically.

3. Relative Paths (For advanced users)

If you open the terminal already inside the folder where your PDFs are located, simply use the file names or a dot .:

  • For the current folder: just type . (a single dot means "the folder I am currently in").
  • For a file in the same folder: just write the name, e.g., document.pdf.

🧱 Step-by-Step Usage Example

Here is what you will see on screen while running the program using drag & drop:

==================================================
 📄 PDF MANAGEMENT UTILITY (Local & Private)
==================================================
1. Merge all PDFs (alphabetically) in a folder
2. Extract page range from a PDF
3. Exit

Select an option (1-3): 1

Path to the folder containing PDFs: [Drag & drop folder here to save time] -> C:\Users\John\Desktop\Contracts
Output file name (e.g. merged.pdf) [Default: merged.pdf]: contracts_2026_complete.pdf

🔍 Found 3 PDF files. Starting merge...
  └─ Adding: 01_january.pdf
  └─ Adding: 02_february.pdf
  └─ Adding: 03_march.pdf
✅ Merge completed successfully! Saved to: contracts_2026_complete.pdf

Why this tool's approach wins

  • 100% Offline: Your data stays exclusively on your computer.
  • No Limits: You can merge 5 GB files or thousands of pages without slowdowns or running out of trial attempts.
  • Extensible Automation: You can import the merge_pdfs and extract_pages functions into other more complex scripts (e.g., to automatically process monthly reports or invoices).


Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment