DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

How to take screenshots and generate PDFs in Ruby on Rails

How to Take Screenshots and Generate PDFs in Ruby on Rails

Rails developers have a few standard options for PDF generation: WickedPDF (wraps wkhtmltopdf), PDFKit (same), Prawn (draws PDFs programmatically), or Grover (wraps Puppeteer). Each adds a system dependency, a binary, or a Node.js runtime to your stack.

For screenshots there's no clean native option — most teams end up shelling out to Chrome.

Here's the alternative: one HTTP call, binary response, no system dependencies.

Screenshot from a URL

require 'net/http'
require 'json'
require 'uri'

def screenshot(url)
  uri = URI('https://pagebolt.dev/api/v1/screenshot')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = ENV['PAGEBOLT_API_KEY']
  request['Content-Type'] = 'application/json'
  request.body = { url: url, fullPage: true, blockBanners: true }.to_json

  response = http.request(request)
  response.body
end

# Save to disk
File.binwrite('screenshot.png', screenshot('https://example.com'))
Enter fullscreen mode Exit fullscreen mode

Or with the faraday gem:

def screenshot(url)
  conn = Faraday.new('https://pagebolt.dev') do |f|
    f.response :raise_error
  end

  response = conn.post('/api/v1/screenshot') do |req|
    req.headers['x-api-key'] = ENV['PAGEBOLT_API_KEY']
    req.headers['Content-Type'] = 'application/json'
    req.body = { url: url, fullPage: true, blockBanners: true }.to_json
  end

  response.body
end
Enter fullscreen mode Exit fullscreen mode

PDF from a URL

def pdf_from_url(url)
  uri = URI('https://pagebolt.dev/api/v1/pdf')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = ENV['PAGEBOLT_API_KEY']
  request['Content-Type'] = 'application/json'
  request.body = { url: url, blockBanners: true }.to_json

  http.request(request).body
end
Enter fullscreen mode Exit fullscreen mode

PDF from an ERB template (replacing WickedPDF)

def pdf_from_template(template_name, locals = {})
  # Render your existing ERB template to an HTML string
  html = ApplicationController.renderer.render(
    template: template_name,
    layout: 'pdf',
    locals: locals
  )

  uri = URI('https://pagebolt.dev/api/v1/pdf')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = ENV['PAGEBOLT_API_KEY']
  request['Content-Type'] = 'application/json'
  request.body = { html: html }.to_json

  http.request(request).body
end
Enter fullscreen mode Exit fullscreen mode

Use it in a controller action:

class InvoicesController < ApplicationController
  def show
    @invoice = Invoice.find(params[:id])

    respond_to do |format|
      format.html
      format.pdf do
        pdf = pdf_from_template('invoices/show', invoice: @invoice)
        send_data pdf,
          filename: "invoice-#{@invoice.id}.pdf",
          type: 'application/pdf',
          disposition: 'attachment'
      end
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

No wkhtmltopdf binary, no Node.js sidecar, no Chromium layer. The existing ERB templates render as before — just swap the PDF generation step.

Narrated video recording

Same pattern, one more endpoint:

def record_video(steps, script)
  uri = URI('https://pagebolt.dev/api/v1/video')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request['x-api-key'] = ENV['PAGEBOLT_API_KEY']
  request['Content-Type'] = 'application/json'
  request.body = {
    steps: steps,
    audioGuide: { enabled: true, voice: 'nova', script: script },
    pace: 'slow',
    frame: { enabled: true, style: 'macos' }
  }.to_json

  http.request(request).body
end
Enter fullscreen mode Exit fullscreen mode

Heroku / serverless deployment

No buildpacks, no apt-get, no binary layer. Add PAGEBOLT_API_KEY to your environment and deploy as normal. The capture runs on PageBolt's infrastructure.


Try it free — 100 requests/month, no credit card. → pagebolt.dev

Top comments (0)