PDF Blocks
PricingSupport
Start Free
Go to Page

Splitting a PDF and handling the output

Call a split action, choose ZIP, JSON, or multipart via the Accept header, and unpack every output part in code.

A split action turns one PDF into several. Unlike every other action, the response is a set of documents rather than a single PDF, and you choose how they are packaged with the Accept request header: a ZIP archive (the default), a JSON envelope of base64-encoded documents, or a multipart/mixed body. This guide picks a split action, requests each format, and unpacks the parts in code.

Pick a split action

Four actions split a document in different ways. They share the same output contract, so the unpacking code below works for all of them.

Action Splits by Key field
Split by page count (split_by_page_count) fixed number of pages per part page_count
Split at page (split_at_page) one boundary into two parts page
Split by file size (split_by_size) a maximum byte size per part maximum_bytes
Split into page groups (split_by_groups) explicit groups you define groups

The examples use split_by_page_count with page_count=10. Swap the route and field to use any other split action.

Choose an output format

Set the Accept header to request a format. Output documents are always named 00001.pdf, 00002.pdf, and so on, in order.

Accept Response body How to read it
application/zip (default) A ZIP archive, one entry per document Unzip the archive
application/json A JSON envelope with a base64 documents[] array Decode each content
multipart/mixed One application/pdf part per document Read parts in order

Omit Accept entirely and you get the ZIP. An Accept header that matches none of these three is answered with 406 Not Acceptable. See Response formats for the full contract.

Get a ZIP (the default)

With no Accept header, the response is a ZIP archive. Save it, then iterate its entries.

cURLbash
curl https://api.pdfblocks.com/v1/split_by_page_count \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F page_count=10 \
  -o parts.zip

unzip parts.zip -d parts/
# parts/00001.pdf  parts/00002.pdf  parts/00003.pdf …
Pythonpython
# pip install requests
import io
import zipfile
import requests

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/split_by_page_count',
        headers={'X-API-Key': 'your_api_key'},  # no Accept → ZIP
        files={'file': file},
        data={'page_count': 10},
    )
response.raise_for_status()

with zipfile.ZipFile(io.BytesIO(response.content)) as archive:
    print(archive.namelist())  # ['00001.pdf', '00002.pdf', …]
    archive.extractall('parts')
Gogo
package main

import (
	"archive/zip"
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
)

func main() {
	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)
	file, _ := os.Open("input.pdf")
	defer file.Close()
	part, _ := form.CreateFormFile("file", "input.pdf")
	io.Copy(part, file)
	form.WriteField("page_count", "10")
	form.Close()

	req, _ := http.NewRequest("POST",
		"https://api.pdfblocks.com/v1/split_by_page_count", &buf)
	req.Header.Set("Content-Type", form.FormDataContentType())
	req.Header.Set("X-API-Key", "your_api_key")
	// No Accept header → ZIP.

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	archive, _ := zip.NewReader(bytes.NewReader(body), int64(len(body)))
	os.MkdirAll("parts", 0755)
	for _, entry := range archive.File {
		in, _ := entry.Open()
		out, _ := os.Create(filepath.Join("parts", entry.Name))
		io.Copy(out, in)
		out.Close()
		in.Close()
	}
}

Get JSON

Set Accept: application/json to receive an envelope instead. Each document carries its name, base64-encoded content, and content_type:

{
  "documents": [
    { "name": "00001.pdf", "content": "JVBERi0xLjcK…", "content_type": "application/pdf" },
    { "name": "00002.pdf", "content": "JVBERi0xLjcK…", "content_type": "application/pdf" }
  ]
}

JSON is convenient when the caller wants the document names alongside the bytes, or when a transport is easier to handle as text than as a binary archive. Decode each content from base64 to recover the PDF.

cURLbash
curl https://api.pdfblocks.com/v1/split_by_page_count \
  -H 'X-API-Key: your_api_key' \
  -H 'Accept: application/json' \
  -F file=@input.pdf \
  -F page_count=10 \
  -o parts.json
Pythonpython
# pip install requests
import base64
import requests

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/split_by_page_count',
        headers={'X-API-Key': 'your_api_key', 'Accept': 'application/json'},
        files={'file': file},
        data={'page_count': 10},
    )
response.raise_for_status()

for document in response.json()['documents']:
    with open(document['name'], 'wb') as out:
        out.write(base64.b64decode(document['content']))
Node.jsjavascript
// Node.js 18+
import { readFile, writeFile } from 'node:fs/promises';

const body = new FormData();
body.set('file', new Blob([await readFile('input.pdf')]), 'input.pdf');
body.set('page_count', '10');

const response = await fetch('https://api.pdfblocks.com/v1/split_by_page_count', {
  method: 'POST',
  headers: { 'X-API-Key': 'your_api_key', Accept: 'application/json' },
  body,
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);

const { documents } = await response.json();
for (const document of documents) {
  await writeFile(document.name, Buffer.from(document.content, 'base64'));
}

Get multipart/mixed

Set Accept: multipart/mixed to stream one application/pdf part per document, each with a Content-Disposition naming it 00001.pdf, 00002.pdf, and so on. Prefer this when you want to handle each part as it arrives rather than hold a whole archive in memory. Most languages have a multipart parser — for Python, requests-toolbelt decodes the response directly:

cURLbash
curl https://api.pdfblocks.com/v1/split_by_page_count \
  -H 'X-API-Key: your_api_key' \
  -H 'Accept: multipart/mixed' \
  -F file=@input.pdf \
  -F page_count=10 \
  -o parts.multipart
Pythonpython
# pip install requests requests-toolbelt
import requests
from requests_toolbelt.multipart.decoder import MultipartDecoder

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/split_by_page_count',
        headers={'X-API-Key': 'your_api_key', 'Accept': 'multipart/mixed'},
        files={'file': file},
        data={'page_count': 10},
    )
response.raise_for_status()

for index, part in enumerate(MultipartDecoder.from_response(response).parts, start=1):
    with open(f'{index:05d}.pdf', 'wb') as out:
        out.write(part.content)

Pitfalls

  • A 406 means your Accept didn’t match. Send exactly application/zip, application/json, or multipart/mixed (or no Accept at all). A stray application/pdf or */* from an HTTP client’s defaults is a common cause — set the header explicitly.
  • Large splits produce large responses. A big document split into many parts can be a sizeable archive. Stream the response to disk instead of holding it in memory, or use multipart/mixed to process each part as it arrives. See Working with large files.
  • A single oversize page. With Split by file size, a page larger than maximum_bytes on its own is returned as its own part that exceeds the limit — it can’t be split further. Expect the occasional part to be bigger than the cap.