PDFShift is a specialized HTML-to-PDF API. Its headless Chrome renderer handles complex CSS, JavaScript-rendered content, and print-specific styling — the things that matter when generating invoices, reports, and documents from HTML templates. If that's your primary use case, PDFShift is purpose-built for it.
But PDFShift users often convert other file types too — images, office documents — using it as a general conversion API. For those non-HTML conversions, and for simple HTML content, ChangeThisFile is cheaper and simpler. This guide helps you identify which conversions should migrate and which should stay.
When migrating from PDFShift makes sense
You're using PDFShift for non-HTML conversions. PDFShift is built for HTML→PDF, but some users route JPG, PNG, DOCX, or other files through it as well. ChangeThisFile covers 690 format pairs — those non-HTML routes cost less and run faster on a purpose-built conversion API.
Your HTML content is simple. Server-generated HTML from templates (reports, invoices, emails with basic CSS, data exports) often converts cleanly via LibreOffice. If your HTML doesn't require JavaScript rendering or complex CSS features, the quality gap between PDFShift and ChangeThisFile may not matter in practice.
Cost is your primary driver. PDFShift charges per conversion starting at $9/month for 200 conversions ($0.045/each). ChangeThisFile's free tier covers 1,000 conversions/month. At low volumes, the savings are immediate and significant.
Who should NOT migrate from PDFShift:
- Your HTML uses JavaScript rendering (React, Vue, Angular single-page content)
- Your layouts rely on Flexbox, Grid, or complex CSS positioning
- You need CSS
@pagerules, print media queries, or specific page dimensions - You need custom headers, footers, or watermarks on generated PDFs
- PDF output quality is customer-facing (invoices, contracts, branded documents)
For those cases, PDFShift's Chrome renderer is the right tool. LibreOffice's HTML rendering is not a drop-in replacement for a real browser engine.
Cost comparison
| Volume/month | PDFShift (est.) | ChangeThisFile | Monthly savings |
|---|---|---|---|
| 200 conversions | $9/mo (entry plan) | $0 (free tier) | $9 |
| 1,000 conversions | $9–18/mo | $0 (free tier) | $9–18 |
| 5,000 conversions | $30–50/mo | $29 (Hobby) | $1–21 |
| 25,000 conversions | $100–180/mo | $99 (Startup) | $1–81 |
PDFShift's billing is conversion-based with monthly plans. Savings are highest at low-to-medium volume where PDFShift's minimum plan cost is high relative to volume.
API endpoint mapping (HTML→PDF and others)
| PDFShift action | ChangeThisFile equivalent |
|---|---|
| POST /v3/pdf (convert HTML to PDF) | POST /v1/convert (target: pdf) |
| Basic Auth (sk_... as username) | Authorization: Bearer ctf_sk_{key} |
| JSON body with "source" (HTML string/URL) | Multipart with file upload |
| CSS sandbox parameter | Not supported |
| Margin, header, footer params | Not supported |
| Webhook URL parameter | Not needed — synchronous |
| response: "base64" option | Binary file in response body |
Note: PDFShift accepts raw HTML strings and URLs as input. ChangeThisFile requires file upload. For URL-based conversion, download the page HTML first, then POST the file.
Code migration: BEFORE and AFTER
# BEFORE: PDFShift (Basic Auth, JSON body with HTML string)
import requests
import base64
PDFSHIFT_KEY = 'sk_your_pdfshift_key'
# Submit HTML string for conversion
resp = requests.post(
'https://api.pdfshift.io/v3/convert/pdf',
auth=(PDFSHIFT_KEY, ''), # key as username, empty password
json={
'source': 'Invoice
Total: $100
',
'landscape': False,
'use_print': True
}
)
with open('invoice.pdf', 'wb') as f:
f.write(resp.content)
# AFTER (for simple HTML): ChangeThisFile
import requests
import io
# Write HTML to a buffer and convert
html_content = b'Invoice
Total: $100
'
response = requests.post(
'https://changethisfile.com/v1/convert',
headers={'Authorization': 'Bearer ctf_sk_your_key'},
files={'file': ('document.html', io.BytesIO(html_content), 'text/html')},
data={'target': 'pdf'}
)
with open('invoice.pdf', 'wb') as f:
f.write(response.content)
# For migrating other format conversions (images, docs):
# BEFORE: routing through PDFShift's general convert endpoint
# AFTER: same ChangeThisFile pattern above, change target format
Important: PDFShift accepts HTML as a string in JSON. ChangeThisFile requires a file upload — wrap your HTML string in a BytesIO buffer with the appropriate MIME type.
Auth migration
- Get your CTF key: changethisfile.com/v1/keys/free. Free, no card.
- Switch from Basic Auth to Bearer token: PDFShift uses Basic Auth with the API key as the username. Replace
auth=(PDFSHIFT_KEY, '')withheaders={'Authorization': f'Bearer {CTF_KEY}'}. - Convert JSON body to multipart: PDFShift accepts HTML as a JSON string. ChangeThisFile requires a file. Wrap your HTML in a BytesIO object or write it to a temp file first.
- Remove PDFShift-specific parameters:
landscape,use_print,margin,header,footer,sandbox— these don't translate to ChangeThisFile. For page layout control in generated PDFs, use CSS@pagerules and print media queries in your HTML before converting.
Rollback plan
PDFShift plans are monthly — keep your subscription active during the parallel-run period:
- Route conversions through a backend function that accepts a
backendparameter. Switching back is a one-line change. - Compare PDF output side-by-side for your actual templates. This is the most important step for this migration — don't skip it.
- If any template shows layout issues with ChangeThisFile output, route that specific template back to PDFShift. Some templates will be fine; others won't.
- Cancel PDFShift only after validating output quality for your full template set.
Common migration questions
Will my invoice/report PDFs look the same?
Probably not identical. PDFShift uses a real Chromium browser engine. ChangeThisFile uses LibreOffice. For simple HTML with basic CSS (tables, text, a few images), output is often close enough. For layouts with Flexbox, Grid, custom fonts loaded via @font-face, or JavaScript-rendered content, PDFShift will produce better output.
Does ChangeThisFile support converting PDFs back to HTML/DOCX?
Yes — PDF→DOCX, PDF→HTML, PDF→TXT, and PDF→JPG/PNG are all supported. PDFShift doesn't convert from PDF. This is an area where ChangeThisFile has broader coverage.
Can I pass a URL to ChangeThisFile like I can to PDFShift?
No — ChangeThisFile requires file upload. Download the URL's HTML content, then POST it as a file. Two steps instead of one.
What about PDFShift's webhook support?
ChangeThisFile is synchronous — no webhook needed. The converted file is in the HTTP response. If you used PDFShift webhooks to handle async completion, remove that logic and use the response directly.
PDFShift is the better tool if CSS layout fidelity in PDF output matters to you. ChangeThisFile is the better tool if you're converting non-HTML files, or if your HTML is simple enough that LibreOffice handles it cleanly. Get a free API key and test your actual templates before deciding.