Sample request
cURL
curl --request POST \
--url 'https://api.pdf.co/v2/pdf/compress' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf"
}'
const response = await fetch(
"https://api.pdf.co/v2/pdf/compress",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY",
},
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
compressionLevel: "medium",
colorQuality: 60,
name: "compressed.pdf",
}),
}
);
const result = await response.json();
if (!response.ok || result.error) {
throw new Error(result.message ?? "PDF.co request failed");
}
console.log(result.url);
import requests
response = requests.post(
"https://api.pdf.co/v2/pdf/compress",
headers={"x-api-key": "YOUR_API_KEY"},
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel": "medium",
"colorQuality": 60,
"name": "compressed.pdf",
},
)
result = response.json()
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co request failed"))
print(result["url"])
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
["compressionLevel"] = "medium",
["colorQuality"] = 60,
["name"] = "compressed.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v2/pdf/compress",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf\", \"compressionLevel\": \"medium\", \"colorQuality\": 60, \"name\": \"compressed.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v2/pdf/compress")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel" => "medium",
"colorQuality" => 60,
"name" => "compressed.pdf",
]);
$curl = curl_init("https://api.pdf.co/v2/pdf/compress");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 2,
"error": false,
"status": 200,
"credits": 70,
"remainingCredits": 999860,
"duration": 8768,
"url": "https://pdf-temp-files.s3.amazonaws.com/example/sample.pdf",
"name": "sample.pdf",
"outputLinkValidTill": "2026-08-08T12:00:00+00:00"
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 408,
"message": "The server timed out waiting for the request."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 441,
"message": "Invalid Password. Password protected document."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 443,
"message": "Permissions. The operation is prohibited by document security settings."
}
{
"error": true,
"status": 444,
"message": "Profiles parsing error. Please ensure that the configuration is supported."
}
{
"error": true,
"status": 445,
"message": "Timeout error. For large documents, use asynchronous mode (async=true) and check status via /job/check."
}
{
"error": true,
"status": 446,
"message": "Some files required for conversion are missing."
}
{
"error": true,
"status": 447,
"message": "Invalid template."
}
{
"error": true,
"status": 448,
"message": "Invalid URL or HTML. Ensure the provided URL is valid and accessible."
}
{
"error": true,
"status": 449,
"message": "Invalid index range. Page index is out of range."
}
{
"error": true,
"status": 450,
"message": "Invalid page range specified."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
cURL
curl --request POST \
--url 'https://api.pdf.co/v2/pdf/compress' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf"
}'
const response = await fetch(
"https://api.pdf.co/v2/pdf/compress",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY",
},
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
compressionLevel: "medium",
colorQuality: 60,
name: "compressed.pdf",
}),
}
);
const result = await response.json();
if (!response.ok || result.error) {
throw new Error(result.message ?? "PDF.co request failed");
}
console.log(result.url);
import requests
response = requests.post(
"https://api.pdf.co/v2/pdf/compress",
headers={"x-api-key": "YOUR_API_KEY"},
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel": "medium",
"colorQuality": 60,
"name": "compressed.pdf",
},
)
result = response.json()
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co request failed"))
print(result["url"])
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
["compressionLevel"] = "medium",
["colorQuality"] = 60,
["name"] = "compressed.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v2/pdf/compress",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf\", \"compressionLevel\": \"medium\", \"colorQuality\": 60, \"name\": \"compressed.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v2/pdf/compress")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel" => "medium",
"colorQuality" => 60,
"name" => "compressed.pdf",
]);
$curl = curl_init("https://api.pdf.co/v2/pdf/compress");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 2,
"error": false,
"status": 200,
"credits": 70,
"remainingCredits": 999860,
"duration": 8768,
"url": "https://pdf-temp-files.s3.amazonaws.com/example/sample.pdf",
"name": "sample.pdf",
"outputLinkValidTill": "2026-08-08T12:00:00+00:00"
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 408,
"message": "The server timed out waiting for the request."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 441,
"message": "Invalid Password. Password protected document."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 443,
"message": "Permissions. The operation is prohibited by document security settings."
}
{
"error": true,
"status": 444,
"message": "Profiles parsing error. Please ensure that the configuration is supported."
}
{
"error": true,
"status": 445,
"message": "Timeout error. For large documents, use asynchronous mode (async=true) and check status via /job/check."
}
{
"error": true,
"status": 446,
"message": "Some files required for conversion are missing."
}
{
"error": true,
"status": 447,
"message": "Invalid template."
}
{
"error": true,
"status": 448,
"message": "Invalid URL or HTML. Ensure the provided URL is valid and accessible."
}
{
"error": true,
"status": 449,
"message": "Invalid index range. Page index is out of range."
}
{
"error": true,
"status": 450,
"message": "Invalid page range specified."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
Document, File & System
PDF Compress
Compress a PDF with ready-to-use presets or advanced image and font controls.
Sample request
cURL
curl --request POST \
--url 'https://api.pdf.co/v2/pdf/compress' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf"
}'
const response = await fetch(
"https://api.pdf.co/v2/pdf/compress",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY",
},
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
compressionLevel: "medium",
colorQuality: 60,
name: "compressed.pdf",
}),
}
);
const result = await response.json();
if (!response.ok || result.error) {
throw new Error(result.message ?? "PDF.co request failed");
}
console.log(result.url);
import requests
response = requests.post(
"https://api.pdf.co/v2/pdf/compress",
headers={"x-api-key": "YOUR_API_KEY"},
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel": "medium",
"colorQuality": 60,
"name": "compressed.pdf",
},
)
result = response.json()
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co request failed"))
print(result["url"])
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
["compressionLevel"] = "medium",
["colorQuality"] = 60,
["name"] = "compressed.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v2/pdf/compress",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf\", \"compressionLevel\": \"medium\", \"colorQuality\": 60, \"name\": \"compressed.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v2/pdf/compress")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel" => "medium",
"colorQuality" => 60,
"name" => "compressed.pdf",
]);
$curl = curl_init("https://api.pdf.co/v2/pdf/compress");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 2,
"error": false,
"status": 200,
"credits": 70,
"remainingCredits": 999860,
"duration": 8768,
"url": "https://pdf-temp-files.s3.amazonaws.com/example/sample.pdf",
"name": "sample.pdf",
"outputLinkValidTill": "2026-08-08T12:00:00+00:00"
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 408,
"message": "The server timed out waiting for the request."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 441,
"message": "Invalid Password. Password protected document."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 443,
"message": "Permissions. The operation is prohibited by document security settings."
}
{
"error": true,
"status": 444,
"message": "Profiles parsing error. Please ensure that the configuration is supported."
}
{
"error": true,
"status": 445,
"message": "Timeout error. For large documents, use asynchronous mode (async=true) and check status via /job/check."
}
{
"error": true,
"status": 446,
"message": "Some files required for conversion are missing."
}
{
"error": true,
"status": 447,
"message": "Invalid template."
}
{
"error": true,
"status": 448,
"message": "Invalid URL or HTML. Ensure the provided URL is valid and accessible."
}
{
"error": true,
"status": 449,
"message": "Invalid index range. Page index is out of range."
}
{
"error": true,
"status": 450,
"message": "Invalid page range specified."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
cURL
curl --request POST \
--url 'https://api.pdf.co/v2/pdf/compress' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf"
}'
const response = await fetch(
"https://api.pdf.co/v2/pdf/compress",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY",
},
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
compressionLevel: "medium",
colorQuality: 60,
name: "compressed.pdf",
}),
}
);
const result = await response.json();
if (!response.ok || result.error) {
throw new Error(result.message ?? "PDF.co request failed");
}
console.log(result.url);
import requests
response = requests.post(
"https://api.pdf.co/v2/pdf/compress",
headers={"x-api-key": "YOUR_API_KEY"},
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel": "medium",
"colorQuality": 60,
"name": "compressed.pdf",
},
)
result = response.json()
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co request failed"))
print(result["url"])
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
["compressionLevel"] = "medium",
["colorQuality"] = 60,
["name"] = "compressed.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v2/pdf/compress",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf\", \"compressionLevel\": \"medium\", \"colorQuality\": 60, \"name\": \"compressed.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v2/pdf/compress")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel" => "medium",
"colorQuality" => 60,
"name" => "compressed.pdf",
]);
$curl = curl_init("https://api.pdf.co/v2/pdf/compress");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 2,
"error": false,
"status": 200,
"credits": 70,
"remainingCredits": 999860,
"duration": 8768,
"url": "https://pdf-temp-files.s3.amazonaws.com/example/sample.pdf",
"name": "sample.pdf",
"outputLinkValidTill": "2026-08-08T12:00:00+00:00"
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 408,
"message": "The server timed out waiting for the request."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 441,
"message": "Invalid Password. Password protected document."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 443,
"message": "Permissions. The operation is prohibited by document security settings."
}
{
"error": true,
"status": 444,
"message": "Profiles parsing error. Please ensure that the configuration is supported."
}
{
"error": true,
"status": 445,
"message": "Timeout error. For large documents, use asynchronous mode (async=true) and check status via /job/check."
}
{
"error": true,
"status": 446,
"message": "Some files required for conversion are missing."
}
{
"error": true,
"status": 447,
"message": "Invalid template."
}
{
"error": true,
"status": 448,
"message": "Invalid URL or HTML. Ensure the provided URL is valid and accessible."
}
{
"error": true,
"status": 449,
"message": "Invalid index range. Page index is out of range."
}
{
"error": true,
"status": 450,
"message": "Invalid page range specified."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
Try it live: PDF Compress → API Tester — send a real request from your browser.
POST /v2/pdf/compress
This is the current PDF compression endpoint. The legacy PDF Optimize V1 endpoint is deprecated.
Quick start
A request containing onlyurl automatically uses the medium preset, so you can start compressing immediately.
Start with the
medium preset for balanced compression. Choose another preset only when you need lighter or stronger compression.To see the request size limits, please refer to the Request Size Limits.
Choose a preset
For most files, choose one of fourcompressionLevel values. You do not need to understand the advanced configuration to use them.
low— Light compression with the highest image resolution.medium— Balanced compression based on Adobe Standard resolution targets.high— Stronger compression with lower image resolution.aggressive— The smallest images and strongest compression of the four presets.
colorQuality from 1 to 100. Higher values preserve more color and grayscale image quality and usually produce larger files. The default is 60.
Preset request body
{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/pdf-compress/sample.pdf",
"compressionLevel": "high"
}
Preset resolution targets
Preset resolution targets
Exact PPI thresholds used by each preset.
| Preset | Color and grayscale | Monochrome |
|---|---|---|
low | 200 PPI when above 300 PPI | 400 PPI when above 600 PPI |
medium | 150 PPI when above 225 PPI | 300 PPI when above 450 PPI |
high | 127 PPI when above 172 PPI | 180 PPI when above 270 PPI |
aggressive | 96 PPI when above 120 PPI | 100 PPI when above 150 PPI |
Request body
Attributes are case-sensitive and should be inside JSON for POST request. for example:
{ "url": "https://example.com/file1.pdf" } There are no query parameters.string
required
URL of the source PDF. The endpoint processes the complete document. The URL must be reachable by PDF.co — see supported file sources. For a protected source location, provide a temporary or presigned URL.
string
Ready-to-use compression profile:
low, medium, high, or aggressive. When omitted, medium is applied. Presets also enable font subsetting and font stream compression.integer
default:"60"
JPEG quality for color and grayscale images, from
1 for the smallest file and lowest quality to 100 for the highest quality. It can be used with or without compressionLevel.The previously published
compression_level and color_quality names are still accepted for backward compatibility. Use compressionLevel and colorQuality in new integrations.string
Password for opening an encrypted source PDF. Omit it for an unprotected PDF.
boolean
default:"false"
Set to
true for large or long-running documents. The initial response includes jobId; use the Background Job Check endpoint to retrieve the final status. Also see Webhooks & Callbacks.string
Callback URL notified when an asynchronous job finishes. Use it with
async: true.string
Output file name. The endpoint appends
.pdf when needed. If omitted, it derives the name from url when possible.integer
default:"60"
Number of minutes before the temporary output URL expires. After this period, generated files are deleted from PDF.co Temporary Files Storage. The maximum retention depends on your subscription plan. To store permanent input files (e.g. re-usable images, pdf templates, documents) consider using PDF.co Built-In Files Storage.
The current V2 Compress implementation does not use
httpusername or httppassword. The old profiles.outputDataFormat and profiles.JPEGQuality descriptions also do not apply to this endpoint.Advanced configuration
Useconfig only when a preset is not enough. It is a partial object: you only send the values you want to override.
- PDF.co starts with the standard configuration.
- It applies
medium, or the selectedcompressionLevel. - It applies
colorQuality, when supplied. - It deep-merges
configas the final override.
How presets and config work together
How presets and config work together
| Request | Image resolution | Color and grayscale encoding | Fonts |
|---|---|---|---|
url only | Medium targets | JPEG, quality 60 | Subset and compress |
compressionLevel | Targets from the selected preset | JPEG, quality 60 unless overridden | Subset and compress |
colorQuality only | Medium targets | JPEG at the selected quality | Subset and compress |
config only | Medium targets with explicit overrides | JPEG, quality 60 unless overridden | Subset and compress unless overridden |
Preset or quality plus config | Selected targets with explicit overrides | Selected JPEG quality unless overridden | Subset and compress unless overridden |
Specify the narrowest override you need. Every omitted value continues to come from the base configuration, or from the preset and
colorQuality you selected.Preset equivalents in config
Preset equivalents in config
Each preset resolves to an effective configuration for the first compression pass. All presets use JPEG quality 60 for color and grayscale images, CCITT Group 4 for monochrome images, font subsetting and compression, and garbage collection level 4. Their resolution targets differ per the Preset resolution targets table above.To represent another preset, change the four PPI values using that table. To represent a different
colorQuality, change both JPEG quality values.The effective values produced by the medium preset:{
"config": {
"images": {
"color": {
"skip": false,
"downsample": {
"skip": false,
"downsample_ppi": 150,
"threshold_ppi": 225
},
"compression": {
"skip": false,
"compression_format": "jpeg",
"compression_params": { "quality": 60 }
}
},
"grayscale": {
"skip": false,
"downsample": {
"skip": false,
"downsample_ppi": 150,
"threshold_ppi": 225
},
"compression": {
"skip": false,
"compression_format": "jpeg",
"compression_params": { "quality": 60 }
}
},
"monochrome": {
"skip": false,
"downsample": {
"skip": false,
"downsample_ppi": 300,
"threshold_ppi": 450
},
"compression": {
"skip": false,
"compression_format": "ccitt_g4",
"compression_params": {}
}
}
},
"fonts": {
"subset": true,
"compress": true
},
"save": {
"garbage": 4
}
}
}
Use
compressionLevel when a preset already fits your needs. The configuration above produces the same first pass, but explicit config values are preserved during the standard fallback retry, so manually copying a complete preset can change fallback behavior.Common config recipes
These examples show only the request fields relevant to the change. Add the same fields to the request body together withurl.
Use custom resolution targets
Use custom resolution targets
Keep the base encoding and fonts, but retain more color and grayscale detail. Images are reduced to 200 PPI only when their effective resolution is above 300 PPI. Monochrome images keep the base settings.
{
"config": {
"images": {
"color": {
"downsample": {
"downsample_ppi": 200,
"threshold_ppi": 300
}
},
"grayscale": {
"downsample": {
"downsample_ppi": 200,
"threshold_ppi": 300
}
}
}
}
}
Re-encode images without resizing them
Re-encode images without resizing them
Preserve pixel dimensions while still applying the selected image encoding. The default preset encoding is JPEG.
{
"config": {
"images": {
"color": { "downsample": { "skip": true } },
"grayscale": { "downsample": { "skip": true } }
}
}
}
Leave monochrome images unchanged
Leave monochrome images unchanged
Do not downsample or re-encode monochrome images.
{
"config": {
"images": {
"monochrome": { "skip": true }
}
}
}
Combine a preset, quality, and config
Combine a preset, quality, and config
Start with
high, preserve more image quality, and make two exceptions. This keeps the high resolution targets, uses color quality 90, leaves monochrome images unchanged, and disables font subsetting. Font stream compression remains enabled.{
"compressionLevel": "high",
"colorQuality": 90,
"config": {
"images": {
"monochrome": { "skip": true }
},
"fonts": {
"subset": false
}
}
}
What each skip setting does
| Setting | What it skips | What can still run |
|---|---|---|
images.<type>.skip | All optimization for that image type | Other image types and fonts |
downsample.skip | Resolution reduction | Image re-encoding |
compression.skip | The selected JPEG, JPEG2000, CCITT, or ZIP compression | Downsampling; resized image data may still be written as PNG |
object
Advanced image, font, and save controls.
Show config properties
Show config properties
object
Settings for color, grayscale, and monochrome images.
Show color / grayscale / monochrome
Show color / grayscale / monochrome
object
color, grayscale & monochrome all use the same object schema:Show properties
Show properties
boolean
default:"false"
Skip both downsampling and re-encoding for this image type.
object
Control resolution reduction.
Show downsample properties
Show downsample properties
boolean
default:"false"
Preserve image dimensions while allowing re-encoding.
integer
default:"150"
Target resolution when the image is above
threshold_ppi. Default is 150 for color and grayscale, 300 for monochrome.integer
default:"225"
Minimum effective resolution that triggers downsampling. Default is
225 for color and grayscale, 450 for monochrome.object
Control image re-encoding.
Show compression properties
Show compression properties
boolean
default:"false"
Skip the selected compression format while allowing downsampling. Resized image data may still be written as PNG.
string
jpeg, jpeg2000, ccitt_g4, ccitt_g3, or zip. Use CCITT for monochrome images.object
JPEG or JPEG2000 quality settings.
Show compression_params properties
Show compression_params properties
integer
JPEG quality from
1 to 100. This field is used only when compression_format is jpeg.string
default:"rates"
JPEG2000 mode:
rates or dB.number[]
JPEG2000 quality layers. When supplied directly without valid layers, the fallback is
[30] for rates or [38.0, 34.0, 30.0] for dB.boolean
default:"false"
JPEG2000 only. Set to
true to use irreversible lossy encoding. The default false uses reversible encoding.integer
default:"0"
JPEG2000 only. Set to
1 to enable the multi-component transform for RGB images, or 0 to disable it.object
Same object schema as
color.object
Same object schema as
color.object
Standard fallback config
Standard fallback config
Fallback base used when the first compression pass is not smaller. A request containing only
url uses medium for its first pass; this fallback has the same image settings but does not subset or compress fonts.{
"images": {
"color": {
"skip": false,
"downsample": { "skip": false, "downsample_ppi": 150, "threshold_ppi": 225 },
"compression": { "skip": false, "compression_format": "jpeg", "compression_params": { "quality": 60 } }
},
"grayscale": {
"skip": false,
"downsample": { "skip": false, "downsample_ppi": 150, "threshold_ppi": 225 },
"compression": { "skip": false, "compression_format": "jpeg", "compression_params": { "quality": 60 } }
},
"monochrome": {
"skip": false,
"downsample": { "skip": false, "downsample_ppi": 300, "threshold_ppi": 450 },
"compression": { "skip": false, "compression_format": "ccitt_g4", "compression_params": {} }
}
},
"fonts": { "subset": false, "compress": false },
"save": { "garbage": 4 }
}
Behavior notes
- Compression results depend on the source PDF. Presets do not promise a fixed reduction, and two levels can produce the same file size.
- When the first compression pass does not produce a smaller PDF, PDF.co retries with the standard configuration while preserving explicit
configoverrides. If the retry is also not smaller, it returns the original PDF. - Each re-encoded image is kept only when its new stream is smaller. If effective PPI cannot be determined, downsampling is skipped but re-encoding can still run at the original dimensions.
Responses
A synchronous success returns the final temporary output URL.Synchronous response
{
"pageCount": 2,
"error": false,
"status": 200,
"credits": 70,
"remainingCredits": 999860,
"duration": 8768,
"url": "https://pdf-temp-files.s3.amazonaws.com/example/sample.pdf",
"name": "sample.pdf",
"outputLinkValidTill": "2026-08-08T12:00:00+00:00"
}
| Field | Type | Description |
|---|---|---|
pageCount | integer | Number of pages in the output PDF. |
error | boolean | false for a successful request. |
status | integer | PDF.co status code. Success returns 200. See Response Codes. |
credits | integer | Credits consumed by the request. |
remainingCredits | integer | Credits remaining for the account. |
duration | integer | Processing duration in milliseconds. |
url | string | Temporary URL of the result. With size protection, it can point to a copy of the original PDF. |
name | string | Output file name. |
outputLinkValidTill | string | UTC timestamp when the temporary URL expires. |
jobId | string | Present in the initial response when async is true. |
jobId and a reserved URL that should be used only after the job succeeds. Poll it via Background Job Check. Errors return error: true with a status code and message. See the response examples and Response Codes.
Inconsistent URL Encoding in cURL Output: When using cURL to make API requests, the output JSON may show URL characters encoded as Unicode escape sequences. For example, the ampersand character (
&) may appear as \u0026 in the cURL output. This is normal JSON encoding behavior and does not affect the validity of the URL. The URL will function correctly when used, as JSON parsers automatically decode these escape sequences. If you’re parsing the response programmatically, your JSON parser will handle this conversion automatically.Was this page helpful?