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)