Screenshot -- Ruby Code Examples
HTTP-based examples for integrating the Nodium Screenshot API with Ruby using the net/http standard library, HTTParty, and Rails.
Basic Screenshot (GET)
The simplest way to capture a screenshot using the standard library.
ruby
require "net/http"
require "uri"
require "json"
api_key = "YOUR_API_KEY"
params = URI.encode_www_form(
url: "https://example.com",
format: "png",
viewport_width: 1280,
viewport_height: 1024
)
uri = URI.parse("https://api.nodium.io/api/v1/screenshot/take?#{params}")
request = Net::HTTP::Get.new(uri)
request["X-Access-Key"] = api_key
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
if response.code == "200"
File.binwrite("screenshot.png", response.body)
puts "Screenshot saved (#{response.body.bytesize} bytes)"
else
error = JSON.parse(response.body)
puts "Error: #{error['error_code']} - #{error['message']}"
endPOST with JSON Body
Use POST for complex configurations with a JSON request body.
ruby
require "net/http"
require "uri"
require "json"
api_key = "YOUR_API_KEY"
uri = URI.parse("https://api.nodium.io/api/v1/screenshot/take")
request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["X-Access-Key"] = api_key
request.body = JSON.generate(
url: "https://example.com",
format: "png",
viewport_width: 1440,
viewport_height: 900,
full_page: true,
image_quality: 90,
block_ads: true,
delay: 1000
)
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.open_timeout = 10
http.read_timeout = 60
http.request(request)
end
if response.code == "200"
File.binwrite("screenshot.png", response.body)
puts "Screenshot saved"
puts "Rendering time: #{response['x-nodium-rendering-seconds']}s"
puts "File size: #{response['x-nodium-size-bytes']} bytes"
else
error = JSON.parse(response.body)
puts "Error [#{error['error_code']}]: #{error['message']}"
endReusable Screenshot Client
A helper class that wraps the API with error handling and retries.
ruby
require "net/http"
require "uri"
require "json"
class NodiumClient
BASE_URL = "https://api.nodium.io/api/v1/screenshot"
def initialize(api_key, max_retries: 3, timeout: 60)
@api_key = api_key
@max_retries = max_retries
@timeout = timeout
end
def take(params)
request_with_retry("#{BASE_URL}/take", params)
end
def animate(params)
request_with_retry("#{BASE_URL}/animate", params)
end
def bulk(params)
request_with_retry("#{BASE_URL}/bulk", params)
end
private
def request_with_retry(url, params)
uri = URI.parse(url)
attempt = 0
loop do
request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["X-Access-Key"] = @api_key
request.body = JSON.generate(params)
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.open_timeout = 10
http.read_timeout = @timeout
http.request(request)
end
return response.body if response.code == "200"
error = begin
JSON.parse(response.body)
rescue JSON::ParserError
{ "error_code" => "unknown", "message" => response.body }
end
# Do not retry client errors (4xx)
if response.code.to_i >= 400 && response.code.to_i < 500
raise "API error [#{error['error_code']}]: #{error['message']}"
end
# Retry server errors (5xx) with exponential backoff
attempt += 1
if attempt > @max_retries
raise "Max retries (#{@max_retries}) exceeded. Last error: #{error['message']}"
end
delay = 2**attempt
puts "Retry #{attempt}/#{@max_retries} after #{delay}s..."
sleep(delay)
end
end
endUsing the Client
ruby
client = NodiumClient.new("YOUR_API_KEY")
data = client.take(
url: "https://example.com",
format: "png",
viewport_width: 1280,
viewport_height: 1024,
full_page: true
)
File.binwrite("screenshot.png", data)
puts "Screenshot saved (#{data.bytesize} bytes)"Error Handling
Handle specific error codes to take appropriate action.
ruby
require "net/http"
require "uri"
require "json"
def capture_screenshot(url, api_key)
uri = URI.parse("https://api.nodium.io/api/v1/screenshot/take")
request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["X-Access-Key"] = api_key
request.body = JSON.generate(url: url, format: "png")
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.read_timeout = 60
http.request(request)
end
if response.code == "200"
return response.body
end
error = JSON.parse(response.body)
case error["error_code"]
when "access_key_required", "access_key_invalid"
raise "Authentication failed: #{error['message']}"
when "screenshots_limit_reached"
raise "Monthly quota exceeded. Upgrade your plan."
when "concurrency_limit_reached"
raise "Too many simultaneous requests. Try again shortly."
when "request_not_valid"
raise "Invalid parameters: #{error['message']}"
when "timeout_error", "network_error", "internal_application_error"
raise "Server error (retryable): #{error['message']}"
when "temporary_unavailable"
raise "Service temporarily unavailable. Try again later."
else
raise "Unknown error [#{error['error_code']}]: #{error['message']}"
end
rescue Net::OpenTimeout, Net::ReadTimeout
raise "Request timed out"
rescue JSON::ParserError
raise "Invalid response from API"
endHTTParty Alternative
Using HTTParty for a more concise API.
Gemfile
ruby
gem "httparty"Example
ruby
require "httparty"
class NodiumScreenshot
include HTTParty
base_uri "https://api.nodium.io/api/v1/screenshot"
def initialize(api_key)
@api_key = api_key
end
def take(params)
response = self.class.post("/take",
headers: {
"Content-Type" => "application/json",
"X-Access-Key" => @api_key,
},
body: params.to_json,
timeout: 60
)
if response.success?
response.body
else
error = response.parsed_response
raise "API error [#{error['error_code']}]: #{error['message']}"
end
end
end
# Usage
client = NodiumScreenshot.new("YOUR_API_KEY")
data = client.take(
url: "https://example.com",
format: "png",
viewport_width: 1280,
viewport_height: 1024
)
File.binwrite("screenshot.png", data)
puts "Screenshot saved"Rails Integration
Configuration
ruby
# config/initializers/nodium.rb
Rails.application.config.nodium_api_key = ENV.fetch("NODIUM_API_KEY")Service Object
ruby
# app/services/screenshot_service.rb
class ScreenshotService
def initialize
@client = NodiumClient.new(
Rails.application.config.nodium_api_key,
max_retries: 3,
timeout: 60
)
end
def capture(url, format: "png", width: 1280, height: 1024, full_page: false)
@client.take(
url: url,
format: format,
viewport_width: width,
viewport_height: height,
full_page: full_page
)
end
def capture_and_store(url, **options)
data = capture(url, **options)
format = options.fetch(:format, "png")
blob = ActiveStorage::Blob.create_and_upload!(
io: StringIO.new(data),
filename: "screenshot-#{Time.current.to_i}.#{format}",
content_type: "image/#{format}"
)
blob
end
endController
ruby
# app/controllers/screenshots_controller.rb
class ScreenshotsController < ApplicationController
def capture
url = params.require(:url)
service = ScreenshotService.new
data = service.capture(url)
send_data data,
type: "image/png",
disposition: "inline",
filename: "screenshot.png"
rescue => e
render json: { error: e.message }, status: :unprocessable_entity
end
endRoute
ruby
# config/routes.rb
Rails.application.routes.draw do
get "/screenshots/capture", to: "screenshots#capture"
endSigned URL Generation
Generate a signed URL by computing an HMAC-SHA256 signature over the query parameters.
ruby
require "openssl"
require "uri"
def generate_signed_url(api_key, secret_key, params, expires_in: 3600)
expires = (Time.now + expires_in).to_i
all_params = params.merge(
access_key: api_key,
expires: expires
)
# Sort parameters for consistent signing
sorted = all_params.sort_by { |k, _| k.to_s }.to_h
string_to_sign = URI.encode_www_form(sorted)
# Compute HMAC-SHA256 signature
signature = OpenSSL::HMAC.hexdigest("SHA256", secret_key, string_to_sign)
# Build the final URL
query = URI.encode_www_form(sorted.merge(signature: signature))
"https://api.nodium.io/api/v1/screenshot/take?#{query}"
end
# Usage
signed_url = generate_signed_url(
"YOUR_API_KEY",
"YOUR_SECRET_KEY",
{
url: "https://example.com",
format: "png",
viewport_width: 1280,
viewport_height: 1024,
},
expires_in: 3600
)
puts signed_urlNext Steps
- API Reference -- Complete reference for all 145+ parameters
- Guides -- Practical guides for common use cases
- Getting Started -- Quick intro and cURL examples