ScreenshotAPI

Ruby

Use ScreenshotAPI from Ruby with net/http or the Faraday gem.

Quick Start

Set your API key

export SCREENSHOTAPI_KEY="sk_live_your_key_here"

Take a screenshot

require "net/http"
require "uri"

api_key = ENV["SCREENSHOTAPI_KEY"]
params = URI.encode_www_form(url: "https://example.com")
uri = URI("https://screenshotapi.to/api/v1/screenshot?#{params}")

req = Net::HTTP::Get.new(uri)
req["x-api-key"] = api_key

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
  http.request(req)
}

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

File.binwrite("screenshot.png", response.body)
puts "Credits remaining: #{response["x-credits-remaining"]}"

Client Class

A reusable client with all screenshot options:

require "net/http"
require "uri"
require "json"

class ScreenshotAPI
  Result = Struct.new(:content, :content_type, :credits_remaining,
                      :screenshot_id, :duration_ms, keyword_init: true)

  def initialize(api_key, base_url: "https://screenshotapi.to")
    @api_key = api_key
    @base_url = base_url
  end

  def capture(url, width: nil, height: nil, full_page: false,
              format: "png", quality: nil, color_scheme: nil,
              wait_until: nil, wait_for_selector: nil, delay: nil)
    params = { url: url }
    params[:width] = width if width
    params[:height] = height if height
    params[:fullPage] = "true" if full_page
    params[:type] = format if format != "png"
    params[:quality] = quality if quality
    params[:colorScheme] = color_scheme if color_scheme
    params[:waitUntil] = wait_until if wait_until
    params[:waitForSelector] = wait_for_selector if wait_for_selector
    params[:delay] = delay if delay

    query = URI.encode_www_form(params)
    uri = URI("#{@base_url}/api/v1/screenshot?#{query}")

    req = Net::HTTP::Get.new(uri)
    req["x-api-key"] = @api_key

    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
      http.request(req)
    }

    unless response.is_a?(Net::HTTPSuccess)
      raise "ScreenshotAPI error #{response.code}: #{response.body}"
    end

    Result.new(
      content: response.body,
      content_type: response["content-type"],
      credits_remaining: response["x-credits-remaining"].to_i,
      screenshot_id: response["x-screenshot-id"],
      duration_ms: response["x-duration-ms"].to_i
    )
  end
end

# Usage
api = ScreenshotAPI.new(ENV["SCREENSHOTAPI_KEY"])

result = api.capture(
  "https://github.com",
  width: 1280,
  height: 720,
  format: "webp",
  quality: 85
)

File.binwrite("github.webp", result.content)
puts "Credits remaining: #{result.credits_remaining}"
puts "Duration: #{result.duration_ms}ms"

Common Patterns

Batch Screenshots with Threads

require "concurrent-ruby"

urls = %w[
  https://example.com
  https://github.com
  https://news.ycombinator.com
]

pool = Concurrent::FixedThreadPool.new(5)
results = Concurrent::Array.new

urls.each_with_index do |url, i|
  pool.post do
    result = api.capture(url)
    File.binwrite("screenshot-#{i}.png", result.content)
    results << { url: url, status: :ok }
  rescue => e
    results << { url: url, status: :error, message: e.message }
  end
end

pool.shutdown
pool.wait_for_termination

results.each do |r|
  if r[:status] == :ok
    puts "✓ #{r[:url]}"
  else
    puts "✗ #{r[:url]}: #{r[:message]}"
  end
end

Rails Controller

class ScreenshotsController < ApplicationController
  def show
    url = params[:url]
    return render json: { error: "url is required" }, status: :bad_request unless url

    result = screenshot_api.capture(url, format: "webp", quality: 80)

    response.headers["Cache-Control"] = "public, max-age=3600"
    send_data result.content, type: result.content_type, disposition: "inline"
  rescue => e
    render json: { error: e.message }, status: :bad_gateway
  end

  private

  def screenshot_api
    @screenshot_api ||= ScreenshotAPI.new(ENV["SCREENSHOTAPI_KEY"])
  end
end

Sinatra Route

require "sinatra"

api = ScreenshotAPI.new(ENV["SCREENSHOTAPI_KEY"])

get "/screenshot" do
  url = params[:url]
  halt 400, { error: "url is required" }.to_json unless url

  result = api.capture(url, format: "webp", quality: 80)
  content_type result.content_type
  cache_control :public, max_age: 3600
  result.content
rescue => e
  halt 502, { error: e.message }.to_json
end

Error Handling

begin
  result = api.capture("https://example.com")
rescue => e
  case e.message
  when /402/
    puts "Out of credits — purchase more at screenshotapi.to"
  when /403/
    puts "Invalid API key — check your configuration"
  else
    puts "Screenshot failed: #{e.message}"
  end
end

On this page