How to Refry a PDF with Python
This Python walkthrough uses requests and a multipart encoder. It completes a PDF -> PostScript -> PDF roundtrip by passing a resource ID from /postscript into /pdf. The complete sample is included below so Python developers can see the file handling, request construction, and response path together.
Why Refry a PDF with Python?
PDF refrying converts a PDF to PostScript and then converts the PostScript into a new PDF. Some prepress-support processes use it when they need a PostScript-based normalization stage between a supplier file and a delivery PDF.
Python is well suited to express that sequence as a small, observable data pipeline: submit the original PDF, capture the PostScript ID, submit that ID with the desired profile, and save the completed PDF bytes. Recording the intermediate and final IDs also gives operators a useful account of what happened in the job.
The roundtrip is not a preservation operation. Keep the source PDF where form fields, tags, layers, annotations, transparency, metadata, or editing capability must survive.
Python Code Example for PDF Refrying
"""Refry a PDF by converting it to PostScript and back to PDF. PDF refrying is the common name for a PDF -> PostScript -> PDF roundtrip. Some print, prepress, and legacy production workflows use it to rebuild or normalize page content, flatten certain PDF constructs, or prepare a file for downstream systems. The process is intentionally lossy and may remove tags, forms, layers, annotations, transparency, metadata, and editability. Use this workflow when a downstream system requires rebuilt page content or a PostScript-based interchange file. The PostScript-to-PDF step uses a custom .joboptions profile in this sample. A .joboptions file contains Adobe Distiller-compatible conversion settings; it is optional, and default settings are used when omitted. pdfRest applies the profile with Datalogics PDF Converter SDK. Datalogics maintains the SDK in partnership with Adobe, using the same Adobe technology that powers Distiller. Run: python3 refry-pdf.py[outputPdf] """ import json import os import sys from pathlib import Path import requests from requests_toolbelt import MultipartEncoder API_URL = os.getenv("PDFREST_URL", "https://api.pdfrest.com").rstrip("/") API_KEY = os.getenv("PDFREST_API_KEY", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") INPUT_PATH = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("/path/to/sample.pdf") JOB_OPTIONS_PATH = ( Path(sys.argv[2]) if len(sys.argv) > 2 else Path("/path/to/custom.joboptions") ) OUTPUT_PATH = Path(__file__).with_name("refried.pdf") if len(sys.argv) > 3: OUTPUT_PATH = Path(sys.argv[3]) def post_multipart(endpoint, fields): """Send a multipart request and return its JSON response.""" form = MultipartEncoder(fields=fields) response = requests.post( f"{API_URL}/{endpoint}", data=form, headers={ "Accept": "application/json", "Content-Type": form.content_type, "Api-Key": API_KEY, }, timeout=120, ) print(f"{endpoint}: {response.status_code}") if not response.ok: raise RuntimeError(f"{endpoint} failed: {response.text}") return response.json() with INPUT_PATH.open("rb") as input_file: postscript = post_multipart( "postscript", { "file": (INPUT_PATH.name, input_file, "application/pdf"), "ps_level": "3", "page_range": "all", "binary_output": "true", "scale": "1", "rotate": "false", "shrink_to_fit": "true", "print_annotations": "true", "output": "refry_intermediate", }, ) with JOB_OPTIONS_PATH.open("rb") as job_options_file: final_pdf = post_multipart( "pdf", { "id": postscript["outputId"], "job_options": ( JOB_OPTIONS_PATH.name, job_options_file, "application/octet-stream", ), "output": "refried", }, ) download = requests.get( f"{API_URL}/resource/{final_pdf['outputId']}?format=file", headers={"Api-Key": API_KEY}, timeout=120, ) download.raise_for_status() OUTPUT_PATH.write_bytes(download.content) print(json.dumps(final_pdf, indent=2)) print(f"Created {OUTPUT_PATH}")
Source: View the sample on GitHub
Breaking Down the Code
Configure the service and input
"""Refry a PDF by converting it to PostScript and back to PDF. PDF refrying is the common name for a PDF -> PostScript -> PDF roundtrip. Some print, prepress, and legacy production workflows use it to rebuild or normalize page content, flatten certain PDF constructs, or prepare a file for downstream systems. The process is intentionally lossy and may remove tags,
For this PDF Refrying example, Python coordinates the two dependent API calls. The Python samples use requests and MultipartEncoder from requests-toolbelt. Install both packages when using the file outside the samples project and keep the API key in environment configuration. The sample’s placeholder path and API key make the moving pieces visible; replace them with a real local path and protected runtime credential before using the request.
Pass the Intermediate Resource to the Next Step
final_pdf = post_multipart(
"pdf",
{
"id": postscript["outputId"],
"job_options": (
JOB_OPTIONS_PATH.name,
job_options_file,
"application/octet-stream",
),
"output": "refried",
},
In the Python workflow, outputId from /postscript becomes the id passed to /pdf. The second request also supplies a custom .joboptions file so the return conversion has an explicit Adobe Distiller-compatible profile, even though default settings are available when the profile is omitted.
Build the multipart request
import requests
from requests_toolbelt import MultipartEncoder
API_URL = os.getenv("PDFREST_URL", "https://api.pdfrest.com").rstrip("/")
API_KEY = os.getenv("PDFREST_API_KEY", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
INPUT_PATH = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("/path/to/sample.pdf")
JOB_OPTIONS_PATH = (
Path(sys.argv[2]) if len(sys.argv) > 2 else Path("/path/to/custom.joboptions")
)
For the PDF Refrying form, MultipartEncoder combines the file tuple and text fields, then exposes a content_type value that includes the generated boundary. That value must be used as the request header.
Read the output resource
def post_multipart(endpoint, fields):
"""Send a multipart request and return its JSON response."""
form = MultipartEncoder(fields=fields)
response = requests.post(
f"{API_URL}/{endpoint}",
data=form,
headers={
"Accept": "application/json",
"Content-Type": form.content_type,
"Api-Key": API_KEY,
},
timeout=120,
After the PDF Refrying call, the sample prints formatted response JSON after a successful request and exits with an error after printing a failed response. Preserve the returned outputId when the next workflow step needs the generated resource.
Beyond the Tutorial
You completed the two-stage refry process in Python and saved the final PDF after both calls succeeded. The intermediate response ID is the important handoff between conversion stages, not merely a status value to print and discard.
Try representative pdf refrying inputs in API Lab. For the authoritative request fields, accepted values, and response contract, consult the pdfRest API Reference Guide. The same request pattern can then be adapted to your Python application’s error handling, retention policy, and delivery workflow.