Need website screenshots from your Ruby or Rails application? This tutorial walks through the fastest approach: call the URLSnap REST API over HTTP. No Selenium, no headless Chrome driver, no ferrum gem to maintain — just a plain HTTP request.
Works in Rails, Sinatra, Sidekiq background jobs, and standalone Ruby scripts.
The standard library covers everything. Optionally install faraday or httparty if you prefer a higher-level HTTP client — we'll show both.
require 'net/http'
require 'json'
require 'uri'
uri = URI('https://urlsnap.dev/api/register')
res = Net::HTTP.post(uri,
{ email: 'you@example.com' }.to_json,
'Content-Type' => 'application/json'
)
data = JSON.parse(res.body)
puts data['key'] # => "us_abc123..."
# Free tier: 20 screenshots/day
require 'net/http'
require 'uri'
API_KEY = 'us_your_key_here' # get free at urlsnap.dev
def screenshot_url(url, output_path, **opts)
params = URI.encode_www_form({
url: url,
format: opts.fetch(:format, 'png'),
full_page: opts.fetch(:full_page, 'false'),
width: opts.fetch(:width, 1280),
height: opts.fetch(:height, 800),
})
uri = URI("https://urlsnap.dev/api/screenshot?#{params}")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req['x-api-key'] = API_KEY
http.request(req) do |resp|
raise "API error #{resp.code}: #{resp.body}" unless resp.code == '200'
File.open(output_path, 'wb') { |f| resp.read_body { |chunk| f.write(chunk) } }
end
end
puts "Screenshot saved to #{output_path}"
end
screenshot_url('https://example.com', 'screenshot.png', full_page: 'true')
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | string | required | Target URL to screenshot |
| width | integer | 1280 | Viewport width in pixels |
| height | integer | 800 | Viewport height in pixels |
| format | string | png | png or jpeg |
| full_page | bool | false | Capture full scrollable page |
| delay | integer | 0 | Wait ms after load, max 5000 |
# Gemfile: gem 'faraday'
require 'faraday'
API_KEY = 'us_your_key_here'
conn = Faraday.new('https://urlsnap.dev') do |f|
f.headers['x-api-key'] = API_KEY
f.options.timeout = 60
end
def screenshot_with_faraday(conn, url, output_path, full_page: false)
response = conn.get('/api/screenshot') do |req|
req.params[:url] = url
req.params[:format] = 'png'
req.params[:full_page] = full_page.to_s
req.params[:width] = 1280
end
raise "Error #{response.status}: #{response.body}" unless response.success?
File.binwrite(output_path, response.body)
puts "Saved #{output_path} (#{response.body.bytesize / 1024}KB)"
end
screenshot_with_faraday(conn, 'https://example.com', 'shot.png', full_page: true)
# app/controllers/previews_controller.rb
class PreviewsController < ApplicationController
API_KEY = ENV.fetch('URLSNAP_API_KEY')
def show
url = params.require(:url)
response = Net::HTTP.start('urlsnap.dev', 443, use_ssl: true) do |http|
params = URI.encode_www_form(url: url, width: 1200, height: 630, format: 'png')
req = Net::HTTP::Get.new("/api/screenshot?#{params}")
req['x-api-key'] = API_KEY
http.request(req)
end
if response.code == '429'
render json: { error: 'Daily limit reached' }, status: :too_many_requests
elsif response.code == '200'
send_data response.body, type: 'image/png', disposition: 'inline'
else
render json: { error: 'Screenshot failed' }, status: :service_unavailable
end
end
end
# app/jobs/screenshot_job.rb
class ScreenshotJob
include Sidekiq::Job
sidekiq_options retry: 3
API_KEY = ENV.fetch('URLSNAP_API_KEY')
def perform(page_id, target_url)
page = Page.find(page_id)
params = URI.encode_www_form(url: target_url, full_page: 'true', format: 'png')
uri = URI("https://urlsnap.dev/api/screenshot?#{params}")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req['x-api-key'] = API_KEY
resp = http.request(req)
raise "API error #{resp.code}" unless resp.code == '200'
# Attach to ActiveStorage
page.screenshot.attach(
io: StringIO.new(resp.body),
filename: "page_#{page_id}.png",
content_type: 'image/png'
)
end
page.update!(screenshot_at: Time.current)
end
end
require 'net/http'
require 'uri'
API_KEY = 'us_your_key_here'
def url_to_pdf(url, output_path, format: 'A4', landscape: false)
params = URI.encode_www_form(url: url, format: format, landscape: landscape.to_s)
uri = URI("https://urlsnap.dev/api/pdf?#{params}")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req['x-api-key'] = API_KEY
resp = http.request(req)
raise "PDF error #{resp.code}" unless resp.code == '200'
File.binwrite(output_path, resp.body)
end
puts "PDF saved to #{output_path}"
end
url_to_pdf('https://example.com', 'page.pdf')
require 'net/http'
require 'json'
API_KEY = 'us_your_key_here'
uri = URI('https://urlsnap.dev/api/me')
req = Net::HTTP::Get.new(uri)
req['x-api-key'] = API_KEY
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
info = JSON.parse(res.body)
puts "Plan: #{info['plan']}"
puts "Used today: #{info['requests_today']}/#{info['daily_limit']}"
puts "All-time: #{info['requests_total']}"
Free tier: 20 screenshots/day. No gem install, no browser setup, no credit card.
Get your free API key →