PDFCraft
Ruby

HTML to PDF in Ruby

One POST, a PDF back. No headless browser to install, no Chromium to keep patched, no fonts to install on the box — the render happens on a warm browser that is already running.

Render HTML to a PDF

require 'net/http'
require 'json'

uri = URI('https://api.pdfcraft.dev/v1/render')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{ENV.fetch('PDFCRAFT_API_KEY')}"
request['Content-Type'] = 'application/json'
request.body = {
  html: '<h1>Invoice 1042</h1>',
  options: { printBackground: true, margin: { top: '20mm' } }
}.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: 60) do |http|
  http.request(request)
end

raise "render failed: #{response.code} #{response.body}" unless response.is_a?(Net::HTTPSuccess)

File.binwrite('invoice.pdf', response.body)

Read a PDF back as JSON

The same key works for extraction. Send a PDF, name the fields you want by the label printed on the page, and get them back with the raw text, a coerced value, a confidence and a bounding box.

require 'base64'

request.body = {
  file: Base64.strict_encode64(File.binread('statement.pdf')),
  schema: { account_number: 'string', closing_balance: 'currency' },
  options: { rows_as_objects: true }
}.to_json

body = JSON.parse(response.body)
puts body.dig('fields', 'closing_balance', 'value')
body.dig('tables', 0, 'rows_as_objects').each { |row| puts row }

What bites in Ruby

Errors are one shape

Every failure is {"error":{"code","message","docs_url"}} with a stable code, so you can switch on error.code rather than parsing prose. The two worth handling explicitly are rate_limited — honour Retry-After — and render_failed, which means your HTML broke rather than ours did.

The same thing in another language

Or try it with no code at all in the playground. A free key is 100 renders a month.