The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Ruby developers can capture a website in two ways: send a request to a hosted screenshot API, or run a browser locally with Ferrum. A hosted API avoids installing and managing Chrome; Ferrum gives you direct browser control but makes your application responsible for the browser process and its resources. This guide shows both approaches, explains what to check for full-page and element captures, and includes a one-request ScreenshotNeo option.
Choose between a hosted API and Ferrum
For a Rails app or Ruby service that needs screenshots without operating a browser, use a hosted API. Your code sends a URL and capture options over HTTP, then handles image or PDF data returned by the service. For local control and browser-level operations, use Ferrum, a Ruby interface to Chrome DevTools Protocol. Ferrum requires Chrome or Chromium to be available to the Ruby process, so your deployment must install and manage it.
| Consideration | Hosted screenshot API | Ferrum with local Chrome/Chromium |
|---|---|---|
| Browser operations | The provider runs the rendering browser; your Ruby app makes HTTP requests. | Your deployment installs the browser and manages its lifecycle and resource use. |
| Authentication | Depends on documented provider capabilities. Check whether it accepts headers, cookies, or an authenticated browser context before targeting a private page. | Your code controls browser navigation and can interact with pages, but you must implement and secure the authentication flow. |
| Capture options | Options vary by provider. Documented examples include full-page, selector, viewport, format, CSS injection, and wait controls. | Direct browser control is available; the exact implementation depends on your Ferrum usage and browser setup. |
| Deployment | No Chrome installation is needed in the Ruby process, but the application depends on the API service and its quotas and policies. | Chrome/Chromium installation, process management, memory, and concurrency are your responsibility. |
| Speed, uptime, and total cost | No neutral benchmark or common total-cost comparison is established by the cited product documentation; check each service’s terms and current plan details. | No neutral benchmark is established here; measure performance and resource use in your own deployment. |
For a managed Ruby screenshot API, ScreenshotNeo is the first option to consider: it removes known consent banners, popups, and chat widgets before capture, bills only clean shots, and its paid plans start at $5 for 3,000 shots. Other documented options include RenderKit’s managed Ruby screenshot API, which describes PNG, JPEG, and WebP output plus full-page, selector, blocking, device-scale, and wait options, and html2img’s Ruby integration, which documents public-URL captures with viewport, full-page, selector, CSS injection, and wait options. Check providers’ current endpoints, authentication support, quotas, pricing, and retention before relying on them.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Make a hosted screenshot request from Ruby
A hosted API call is an HTTP request, not a special Ruby browser feature. The general pattern is to keep the API key on the server, send the target URL and supported options, check the response, and save the returned bytes. The exact endpoint, authentication format, parameter names, and response content vary by provider. The following example is an executable request pattern; replace the endpoint, key header, and payload fields with the service’s documented values.
Ruby with Net::HTTP
require "net/http"
require "json"
require "uri"
endpoint = URI("https://api.example.com/v1/screenshot")
api_key = ENV.fetch("SCREENSHOT_API_KEY")
payload = {
url: "https://example.com",
full_page: true,
format: "png",
viewport: { width: 1440, height: 1000 },
wait_until: "network_idle"
}
request = Net::HTTP::Post.new(endpoint)
request["Authorization"] = "Bearer #{api_key}"
request["Content-Type"] = "application/json"
request.body = JSON.generate(payload)
response = Net::HTTP.start(
endpoint.hostname,
endpoint.port,
use_ssl: endpoint.scheme == "https",
open_timeout: 10,
read_timeout: 90
) { |http| http.request(request) }
unless response.is_a?(Net::HTTPSuccess)
abort "Screenshot API returned #{response.code}: #{response.body}"
end
File.binwrite("page.png", response.body)
puts "Saved page.png (#{response.body.bytesize} bytes)"
This example assumes the API responds with raw PNG bytes. Some services return JSON containing a download URL or encoded image instead; parse that response according to the provider’s documentation rather than writing JSON text to a .png file. Likewise, a provider may use a query parameter or a different header for API-key authentication.
#1 Best Overall
Useful capture options to verify
- Full-page capture: captures beyond the initial viewport, often by expanding or scrolling the rendered page. It can take longer and produce a larger file than a viewport screenshot.
- Element capture: a CSS selector lets you capture one component, such as a chart or invoice panel. Confirm what happens if the selector does not match and whether the service waits for it.
- Viewport and device scale: set width and height for layout; device scale affects pixel density and output size. Provider presets and names differ.
- Wait behavior: a selector wait or delay can help with client-rendered content. Waiting for network idle may not be suitable for pages that maintain long-lived network connections.
- Format: PNG, JPEG, WebP, and PDF availability differs across services. Match the extension and downstream processing to the actual returned content type.
- CSS or blocking: CSS injection, ad or cookie blocking, and request filtering are provider-specific. Do not assume an option exists because another API offers it.
Run a screenshot locally with Ferrum
Ferrum controls Chrome or Chromium through the Chrome DevTools Protocol. This is the self-hosted route: install the gem and a compatible browser in the environment that runs the Ruby process, then navigate, save the image, and close the browser. The documented quick-start pattern uses Ferrum::Browser.new, go_to, screenshot, and quit.
Minimal Ferrum capture
require "ferrum"
browser = Ferrum::Browser.new
begin
browser.go_to("https://example.com")
browser.screenshot(path: "page.png")
ensure
browser.quit
end
puts "Saved page.png"
Install Ferrum through your application’s normal Ruby dependency management and ensure Chrome or Chromium is installed and discoverable by the process. The exact browser installation and launch configuration is deployment-specific. The Ferrum project documentation describes its browser prerequisite and screenshot workflow.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesFor pages that render asynchronously, do not assume navigation completion means every chart, image, or client-rendered widget is ready. Wait for a page-specific condition before capturing, using the wait mechanisms available in your Ferrum version or the application’s own browser interaction flow. A fixed delay is simple but may waste time on fast pages and still be too short on slow ones.
Rank #2
- Used Book in Good Condition
Full-page and selector captures: decide what the page needs
Use a viewport capture when the deliverable is what a visitor sees without scrolling. Use a full-page capture for a whole article, long report, or page audit; it may increase render time, memory use, and output size. A selector capture is a better fit when only one component matters, but it depends on stable page markup and a clear failure path when the element is missing.
For hosted services, the cited product documentation identifies differing feature sets: RenderKit documents full-page and selector options, while html2img documents full-page and selector options for public URL captures. Screenshot API documents GET and POST endpoints, API-key authentication, PNG/JPEG/WebP/PDF output, and advanced POST options. Its current exact option names and endpoint details should be checked in its API documentation before implementation.
For a private page, first establish how the target service authenticates the browser request. The html2img Ruby integration specifically describes publicly reachable URLs; its cited page does not establish private-page support through headers, cookies, or a logged-in browser context. Ferrum may be more appropriate when the workflow requires an application-managed login, but that adds responsibility for credentials, session handling, and browser operations.
Or skip the browser setup
ScreenshotNeo accepts a URL in one GET request and returns a screenshot. This cURL example saves a WebP capture of a public page; for the parameter details and response behavior, see the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers identify the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card.
Performance, reliability, and cost considerations
Keep browser work bounded
Full-page capture, high device scale, and large viewport dimensions can increase work and file size. For Ferrum, browser instances consume resources inside your deployment, so consider how many simultaneous captures your service can safely run and ensure cleanup occurs even when navigation or saving raises an error. For hosted capture, use the provider’s documented timeout and concurrency limits rather than assuming a request will complete within an application default.
Make failures observable
Record the target host, capture mode, elapsed time, response status, and output size without logging API keys or sensitive page contents. Treat a successful HTTP status and a valid image or PDF as separate checks: services that return metadata or an error body may not produce an image despite a response your code can parse.
Rank #4
Compare real operating costs
Hosted services may charge by successful captures, plan quota, or other terms; review current quotas, overages, cache behavior, data retention, and billing definitions. With Ferrum, include browser installation, memory, operational upkeep, and concurrency limits in the cost calculation. Product documentation cited for these approaches does not establish a neutral speed, uptime, or total-cost benchmark.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting Ruby screenshot captures
- Ferrum cannot find or launch Chrome: install Chrome or Chromium in the runtime environment, verify the executable is accessible to the Ruby process, and check the launch configuration for your deployment.
- The output file contains JSON or an error message: inspect the response content type and body before saving. The provider may return a JSON download URL or an error payload rather than raw image bytes.
- The screenshot is blank or missing page content: the page may not have finished client-side rendering. Wait for a meaningful selector or a suitable page condition, and verify that the target URL is reachable from the browser/API environment.
- A selector capture fails or is empty: confirm the selector exists in the rendered DOM, account for delayed rendering, and handle the absent-element case explicitly.
- A private URL returns a login page: a public-URL endpoint may not carry your session. Confirm documented support for request headers, cookies, or authenticated browser contexts; do not send credentials to a service without an appropriate security review.
- Requests time out on long pages: reduce unnecessary full-page or high-resolution work, choose a suitable wait condition, and align the HTTP read timeout with the provider’s documented behavior.
- Concurrent captures exhaust resources: with Ferrum, limit concurrent browser work and reliably close browsers. With a hosted API, check its concurrency and request limits.
Ruby screenshot API questions
Can I use a screenshot API from Rails?
Yes. A Rails server can make the same server-side HTTP request as the Net::HTTP example. Store the key in server-side configuration, not browser-delivered JavaScript, and avoid exposing private page data in logs.
Can a Ruby API screenshot a page behind login?
Sometimes, but support depends on the provider’s documented authentication controls. A public-URL-only integration is not enough to establish authenticated capture support; Ferrum offers local browser control if your application implements the required login flow.
Does a Ruby screenshot request return an image URL or image bytes?
Both response patterns exist. Check the endpoint documentation and content type; the sample Net::HTTP code is for raw image bytes only.
Is Ferrum a screenshot API?
Ferrum is a Ruby library that controls a local Chrome/Chromium browser through DevTools Protocol, rather than a hosted screenshot endpoint.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

