PDF Generation
The pdf mutation navigates to a URL and generates a PDF. Browserless returns the file as a base64-encoded string with options for page format, margins, headers, footers, and background printing.
Basic Usage
Navigate to a URL and capture the page as a PDF. Wait for elements to load before generating to avoid incomplete content.
- BQL Query
- cURL
- Javascript
- Python
- Java
- C#
mutation PDF {
goto(url: "https://example.com") {
status
}
pdf(displayHeaderFooter: true, printBackground: false, format: a0) {
base64
}
}
curl --request POST \
--url 'https://production-sfo.browserless.io/chromium/bql?token=YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/json' \
--data '{"query":"mutation PDF {\n goto(url: \"https://example.com\") {\n status\n }\n\n pdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n }\n}","variables":{},"operationName":"PDF"}'
const endpoint = "https://production-sfo.browserless.io/chromium/bql";
const token = "YOUR_API_TOKEN_HERE";
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({"query":"mutation PDF {\n goto(url: \"https://example.com\") {\n status\n }\n\n pdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n }\n}","variables":{},"operationName":"PDF"})
};
const url = `${endpoint}?token=${token}`;
const response = await fetch(url, options);
const data = await response.json();
console.log(data);
import requests
endpoint = "https://production-sfo.browserless.io/chromium/bql"
query_string = {
"token": "YOUR_API_TOKEN_HERE",
}
headers = {
"Content-Type": "application/json",
}
payload = {
"query": "mutation PDF {\n goto(url: \"https://example.com\") {\n status\n }\n\n pdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n }\n}",
"variables": {},
"operationName": "PDF",
}
response = requests.post(endpoint, params=query_string, headers=headers, json=payload)
print(response.json())
String url = "https://production-sfo.browserless.io/chromium/bql";
String token = "YOUR_API_TOKEN_HERE";
String endpoint = url + "?token=" + token;
String payload = """
{"query":"mutation PDF {\n goto(url: \"https://example.com\") {\n status\n }\n\n pdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n }\n}","variables":{},"operationName":"PDF"}
""";
HttpResponse<String> response = Unirest.post(endpoint)
.header("Content-Type", "application/json")
.body(payload)
.asString();
string url = "https://production-sfo.browserless.io/chromium/bql";
string token = "YOUR_API_TOKEN_HERE";
string endpoint = $"{url}?token={token}";
var payload = new
{
query = @"mutation PDF {
goto(url: ""https://example.com"") {
status
}
pdf(displayHeaderFooter: true, printBackground: false, format: a0) {
base64
}
}",
variables = "",
operationName = "PDF"
};
using (var client = new HttpClient())
{
var jsonPayload = System.Text.Json.JsonSerializer.Serialize(payload);
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(endpoint, content);
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
Setting HTML Content
The content mutation sets the page HTML directly, without navigating to a URL. Use it to generate PDFs from dynamic or server-rendered markup.
- BQL Query
- cURL
- Javascript
- Python
- Java
- C#
mutation PDF {
content(html: "<h1>Hello, World!</h1>") {
status
}
pdf(displayHeaderFooter: true, printBackground: false, format: a0) {
base64
}
}
curl --request POST \
--url 'https://production-sfo.browserless.io/chromium/bql?token=YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/json' \
--data '{"query":"mutation PDF {\ncontent(html: \"<h1>Hello, World!</h1>\") {\n status\n}\n\npdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n}\n}","variables":{},"operationName":"PDF"}'
const endpoint = "https://production-sfo.browserless.io/chromium/bql";
const token = "YOUR_API_TOKEN_HERE";
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({"query":"mutation PDF {\ncontent(html: \"<h1>Hello, World!</h1>\") {\n status\n}\n\npdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n}\n}","variables":{},"operationName":"PDF"})
};
const url = `${endpoint}?token=${token}`;
const response = await fetch(url, options);
const data = await response.json();
console.log(data);
import requests
endpoint = "https://production-sfo.browserless.io/chromium/bql"
query_string = {
"token": "YOUR_API_TOKEN_HERE",
}
headers = {
"Content-Type": "application/json",
}
payload = {
"query": "mutation PDF {\ncontent(html: \"<h1>Hello, World!</h1>\") {\n status\n}\n\npdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n}\n}",
"variables": {},
"operationName": "PDF",
}
response = requests.post(endpoint, params=query_string, headers=headers, json=payload)
print(response.json())
String url = "https://production-sfo.browserless.io/chromium/bql";
String token = "YOUR_API_TOKEN_HERE";
String endpoint = url + "?token=" + token;
String payload = """
{"query":"mutation PDF {\ncontent(html: \"<h1>Hello, World!</h1>\") {\n status\n}\n\npdf(displayHeaderFooter: true, printBackground: false, format: a0) {\n base64\n}\n}","variables":{},"operationName":"PDF"}
""";
HttpResponse<String> response = Unirest.post(endpoint)
.header("Content-Type", "application/json")
.body(payload)
.asString();
string url = "https://production-sfo.browserless.io/chromium/bql";
string token = "YOUR_API_TOKEN_HERE";
string endpoint = $"{url}?token={token}";
var payload = new
{
query = @"mutation PDF {
content(html: ""<h1>Hello, World!</h1>"") {
status
}
pdf(displayHeaderFooter: true, printBackground: false, format: a0) {
base64
}
}",
variables = "",
operationName = "PDF"
};
using (var client = new HttpClient())
{
var jsonPayload = System.Text.Json.JsonSerializer.Serialize(payload);
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(endpoint, content);
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
Adding Header and Footer Templates
Custom header and footer templates let you inject dynamic content into PDFs. Templates support special CSS classes: pageNumber, totalPages, title, url, and date.
Specify font sizes explicitly in header and footer templates (e.g., font-size: 12pt). The default text size is too small to read in most PDF viewers.
- BQL Query
- cURL
- Javascript
- Python
- Java
- C#
mutation addFooterAndHeaderToPDF {
goto(url: "https://www.example.com", waitUntil: networkIdle) {
status
}
invoice: pdf(
format: a4
displayHeaderFooter: true
headerTemplate: "<div style='font-size:12pt; line-height:1.2; width:100%; text-align:center; padding-top:2mm;'><span class='title'></span></div>"
footerTemplate: "<div style='font-size:11pt; line-height:1.2; width:100%; text-align:center; padding-bottom:2mm;'><span class='pageNumber'></span>/<span class='totalPages'></span></div>"
printBackground: true
) {
base64
}
}
curl --request POST \
--url 'https://production-sfo.browserless.io/chromium/bql?token=YOUR_API_TOKEN_HERE' \
--header 'Content-Type: application/json' \
--data '{"query":"mutation addFooterAndHeaderToPDF {\n goto(url: \"https://www.example.com\", waitUntil: networkIdle) {\n status\n }\n invoice: pdf(\n format: a4\n displayHeaderFooter: true\n headerTemplate: \"<div style='\''font-size:12pt; line-height:1.2; width:100%; text-align:center; padding-top:2mm;'\''><span class='\''title'\''></span></div>\"\n footerTemplate: \"<div style='\''font-size:11pt; line-height:1.2; width:100%; text-align:center; padding-bottom:2mm;'\''><span class='\''pageNumber'\''></span>/<span class='\''totalPages'\''></span></div>\"\n printBackground: true\n ) {\n base64\n }\n}","variables":{},"operationName":"addFooterAndHeaderToPDF"}'
const endpoint = "https://production-sfo.browserless.io/chromium/bql";
const token = "YOUR_API_TOKEN_HERE";
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({"query":"mutation addFooterAndHeaderToPDF {\n goto(url: \"https://www.example.com\", waitUntil: networkIdle) {\n status\n }\n invoice: pdf(\n format: a4\n displayHeaderFooter: true\n headerTemplate: \"<div style='font-size:12pt; line-height:1.2; width:100%; text-align:center; padding-top:2mm;'><span class='title'></span></div>\"\n footerTemplate: \"<div style='font-size:11pt; line-height:1.2; width:100%; text-align:center; padding-bottom:2mm;'><span class='pageNumber'></span>/<span class='totalPages'></span></div>\"\n printBackground: true\n ) {\n base64\n }\n}","variables":{},"operationName":"addFooterAndHeaderToPDF"})
};
const url = `${endpoint}?token=${token}`;
const response = await fetch(url, options);
const data = await response.json();
console.log(data);
import requests
endpoint = "https://production-sfo.browserless.io/chromium/bql"
query_string = {
"token": "YOUR_API_TOKEN_HERE",
}
headers = {
"Content-Type": "application/json",
}
payload = {
"query": "mutation addFooterAndHeaderToPDF {\n goto(url: \"https://www.example.com\", waitUntil: networkIdle) {\n status\n }\n invoice: pdf(\n format: a4\n displayHeaderFooter: true\n headerTemplate: \"<div style='font-size:12pt; line-height:1.2; width:100%; text-align:center; padding-top:2mm;'><span class='title'></span></div>\"\n footerTemplate: \"<div style='font-size:11pt; line-height:1.2; width:100%; text-align:center; padding-bottom:2mm;'><span class='pageNumber'></span>/<span class='totalPages'></span></div>\"\n printBackground: true\n ) {\n base64\n }\n}",
"variables": {},
"operationName": "addFooterAndHeaderToPDF",
}
response = requests.post(endpoint, params=query_string, headers=headers, json=payload)
print(response.json())
String url = "https://production-sfo.browserless.io/chromium/bql";
String token = "YOUR_API_TOKEN_HERE";
String endpoint = String.format("%s?token=%s", url, token);
HttpResponse<String> response = Unirest.post(endpoint)
.header("Content-Type", "application/json")
.body("{\"query\":\"mutation addFooterAndHeaderToPDF {\\n goto(url: \\\"https://www.example.com\\\", waitUntil: networkIdle) {\\n status\\n }\\n invoice: pdf(\\n format: a4\\n displayHeaderFooter: true\\n headerTemplate: \\\"<div style='font-size:12pt; line-height:1.2; width:100%; text-align:center; padding-top:2mm;'><span class='title'></span></div>\\\"\\n footerTemplate: \\\"<div style='font-size:11pt; line-height:1.2; width:100%; text-align:center; padding-bottom:2mm;'><span class='pageNumber'></span>/<span class='totalPages'></span></div>\\\"\\n printBackground: true\\n ) {\\n base64\\n }\\n}\",\"variables\":\"\",\"operationName\":\"addFooterAndHeaderToPDF\"}")
.asString();
string url = "https://production-sfo.browserless.io/chromium/bql";
string token = "YOUR_API_TOKEN_HERE";
string endpoint = $"{url}?token={token}";
var payload = new
{
query = @"mutation addFooterAndHeaderToPDF {
goto(url: ""https://www.example.com"", waitUntil: networkIdle) {
status
}
invoice: pdf(
format: a4
displayHeaderFooter: true
headerTemplate: ""<div style='font-size:12pt; line-height:1.2; width:100%; text-align:center; padding-top:2mm;'><span class='title'></span></div>""
footerTemplate: ""<div style='font-size:11pt; line-height:1.2; width:100%; text-align:center; padding-bottom:2mm;'><span class='pageNumber'></span>/<span class='totalPages'></span></div>""
printBackground: true
) {
base64
}
}",
variables = "",
operationName = "addFooterAndHeaderToPDF"
};
using (var client = new HttpClient())
{
var jsonPayload = System.Text.Json.JsonSerializer.Serialize(payload);
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(endpoint, content);
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
Next Steps
Frequently Asked Questions
Can BrowserQL generate PDFs from any web page?
Yes. BrowserQL renders the page in a real browser and generates a PDF using Chrome's print-to-PDF engine. This handles JavaScript-rendered content, custom fonts, and complex layouts.
How do I add headers and footers to generated PDFs?
Use the headerTemplate and footerTemplate parameters in the pdf mutation. These accept HTML strings with special classes like pageNumber and totalPages for dynamic content.
Can I generate a PDF from raw HTML instead of a URL?
Yes. Use the content mutation to load HTML directly into the browser, then call the pdf mutation. This is useful for generating invoices, reports, or documents from dynamic HTML.