PHP integration
Generate PDFs from HTML in PHP
Use PHP’s built-in cURL extension to turn HTML or a URL into a PDF with the CheapPDF API. No Composer package is required.
<?php
$ch = curl_init('https://www.cheap-pdf.com/generate-pdf-public');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POSTFIELDS => [
'apikey' => getenv('CHEAPPDF_API_KEY'),
'filename' => 'hello.pdf',
'fileorhtmlorurl' => '<h1>Hello from PHP</h1>',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
file_put_contents('hello.pdf', base64_decode($result['data']['base64_pdf']));Prerequisites
- PHP 8.1 or later (the client below uses constructor promotion and
readonly; on older PHP, replace those with ordinary properties). - The
curlandjsonextensions, enabled in most PHP installs. - A CheapPDF API key from the Get Started page.
Composer is optional. If your project already uses Guzzle or Symfony HttpClient, the same fields work with them: send a POST with apikey, fileorhtmlorurl and filename.
Keep your API key out of your code
Read the key from an environment variable and call the API from server-side PHP only. Never print it into a page, ship it in JavaScript, or commit it to Git.
If a key leaks, replace it from your dashboard and update the environment variable.
# .env (never commit this file)
CHEAPPDF_API_KEY=your-api-key
# Load it with your framework, or in plain PHP, set it in the web server / PHP-FPM pool:
# fastcgi_param CHEAPPDF_API_KEY your-api-key; (nginx)
# SetEnv CHEAPPDF_API_KEY your-api-key (Apache)A complete minimal integration
A small client class that validates the key, sends the request, checks the response and returns raw PDF bytes.
<?php
final class CheapPdfException extends RuntimeException
{
public function __construct(string $message, public readonly ?string $errorCode = null, public readonly int $httpStatus = 0)
{
parent::__construct($message);
}
}
final class CheapPdfClient
{
private const ENDPOINT = 'https://www.cheap-pdf.com/generate-pdf-public';
public function __construct(private readonly string $apiKey, private readonly int $timeout = 60)
{
if ($apiKey === '') {
throw new InvalidArgumentException('CHEAPPDF_API_KEY is not set.');
}
}
/** @return string Raw PDF bytes */
public function fromHtml(string $html, string $filename = 'document.pdf', array $options = []): string
{
return $this->send(['fileorhtmlorurl' => $html, 'filename' => $filename] + $options);
}
public function fromUrl(string $url, string $filename = 'page.pdf', array $options = []): string
{
return $this->send(['fileorhtmlorurl' => $url, 'filename' => $filename] + $options);
}
private function send(array $fields): string
{
$ch = curl_init(self::ENDPOINT);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_POSTFIELDS => ['apikey' => $this->apiKey] + $fields,
]);
$body = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($body === false) {
throw new CheapPdfException("Network error: $error");
}
$json = json_decode($body, true);
if ($status !== 200 || !is_array($json) || empty($json['success'])) {
throw new CheapPdfException($json['message'] ?? "Conversion failed (HTTP $status)", $json['error'] ?? null, $status);
}
$pdf = base64_decode($json['data']['base64_pdf'] ?? '', true);
if ($pdf === false || !str_starts_with($pdf, '%PDF')) {
throw new CheapPdfException('The response did not contain a valid PDF.');
}
return $pdf;
}
}Using it
<?php
require __DIR__ . '/CheapPdfClient.php';
$client = new CheapPdfClient(getenv('CHEAPPDF_API_KEY'));
try {
$pdf = $client->fromHtml(
'<h1>Invoice #1042</h1><p>Total: $9.00</p>',
'invoice-1042.pdf',
['width' => 800, 'height' => 1100]
);
// Option A: save to disk
file_put_contents(__DIR__ . '/storage/invoice-1042.pdf', $pdf);
// Option B: stream to the browser as a download
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="invoice-1042.pdf"');
header('Content-Length: ' . strlen($pdf));
echo $pdf;
} catch (CheapPdfException $e) {
error_log("PDF failed [{$e->errorCode}]: {$e->getMessage()}");
http_response_code($e->httpStatus === 400 ? 422 : 502);
echo 'We could not generate your PDF right now.';
}Request parameters and response handling
| Field | Type | Notes |
|---|---|---|
apikey | string | Required. Taken from the environment. |
fileorhtmlorurl | string or CURLFile | Required. HTML, a public URL, or new CURLFile('page.html', 'text/html') for a file upload (up to 5 MB). |
filename | string | Required. Ends with .pdf. |
width, height | int | Optional page size in pixels. |
landscape, printBackground | bool as string | Optional. Pass 'true' or 'false'. |
A successful response is JSON with success: true and the PDF base64-encoded in data.base64_pdf. The client decodes it and checks that the bytes start with %PDF before returning them.
Error handling and production considerations
Set timeouts
The client sets a 10 second connect timeout and a 60 second total timeout. Choose values that fit your request time limits.
Do not retry 400 errors
Errors such as invalid_api_key or free_plan_limit_reached will fail again. Surface them instead. Retry network errors and 5xx responses a few times with backoff.
Generate in the background
For large documents or batches, push the work to a queue or cron job rather than making a visitor wait on the request.
Do not log document contents
Log the error code and a document ID, not the HTML or the key.
Cache what does not change
If the same HTML always yields the same PDF, store the result and serve the file.
Validate user-supplied HTML
If users can submit HTML or URLs, treat them as untrusted input and limit what you accept.
Practical example: download an invoice
Render your invoice template to an HTML string with output buffering, pass it to fromHtml(), and stream the result as an attachment, as in generate.php above. For a full workflow with templates and batches, read the invoice PDF generation guide.
PHP FAQ
Do I need Composer to use the CheapPDF API in PHP?
No. PHP's cURL extension is enough. Composer is only needed if you prefer an HTTP library such as Guzzle.
How do I save the generated PDF?
Decode data.base64_pdf with base64_decode() and write the bytes with file_put_contents(), or send them to the browser with a Content-Type: application/pdf header.
Where should I store my API key?
In an environment variable or secret manager, read at runtime with getenv(). Do not commit it or expose it in client-side code.
Can I send an HTML file instead of a string?
Yes. Pass new CURLFile('page.html', 'text/html') as fileorhtmlorurl. Uploaded files must be .html and up to 5 MB.
Add PDF generation to your PHP app
Create an API key and run the quick start in a few minutes.