Rails5 min read · June 10, 2026

Generate PDFs in Ruby on Rails (No wkhtmltopdf Required)

Generate PDFs from HTML in Ruby on Rails using a REST API. No pdf-kit, no system binary — just a Net::HTTP or Faraday call from any Rails controller.

PDF generation in Rails usually means pdf-kit (which wraps wkhtmltopdf and requires a system binary), Prawn (a programmatic builder with no HTML support), or WickedPDF — all of which add server dependencies or rendering limitations.

A hosted REST API removes every constraint. You send HTML, you get PDF bytes back. No gem native extensions, no binary on your server, no Docker image bloat.

Make the Request with Net::HTTP

Ruby's standard library handles this cleanly. No additional gems required:

app/services/pdf_service.rbruby
require 'net/http'
require 'json'

class PdfService
  API_URI = URI('https://platform.htmltopdfapi.co/api/v1/pdf/generate').freeze

  def self.from_html(html, paper_size: 'a4', orientation: 'portrait')
    http         = Net::HTTP.new(API_URI.host, API_URI.port)
    http.use_ssl = true

    req = Net::HTTP::Post.new(API_URI.path)
    req['Authorization'] = "Bearer #{ENV.fetch('HTMLTOPDF_API_KEY')}"
    req['Content-Type']  = 'application/json'
    req['Accept']        = 'application/pdf'
    req.body = { html:, paper_size:, orientation: }.to_json

    res = http.request(req)
    raise "PDF API error #{res.code}" unless res.code == '200'
    res.body
  end
end

Stream from a Rails Controller

app/controllers/invoices_controller.rbruby
class InvoicesController < ApplicationController
  def download
    @invoice = Invoice.find(params[:id])
    authorize @invoice

    html  = render_to_string('invoices/pdf', layout: false)
    bytes = PdfService.from_html(html)

    send_data bytes,
              type:        'application/pdf',
              disposition: 'inline',
              filename:    "invoice-#{@invoice.number}.pdf"
  end
end

Or Use Faraday

If you're already using Faraday in your app:

Faraday snippetruby
conn = Faraday.new('https://platform.htmltopdfapi.co') do |f|
  f.response :raise_error
end

res = conn.post('/api/v1/pdf/generate') do |req|
  req.headers['Authorization'] = "Bearer #{ENV.fetch('HTMLTOPDF_API_KEY')}"
  req.headers['Content-Type']  = 'application/json'
  req.headers['Accept']        = 'application/pdf'
  req.body = { html:, paper_size: 'a4' }.to_json
end

pdf_bytes = res.body

What You Remove

Switching to a REST API removes wkhtmltopdf and its system-level dependencies from every server and Docker image. Your buildpack config disappears, your images shrink, and rendering keeps pace with modern CSS automatically. The engine is updated on the API side.