Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

The quickest local conversion is IMGKit with wkhtmltoimage: pass an HTML string to IMGKit.new, call to_img(:jpeg), and write the returned bytes to a file. For pages that depend on current Chrome CSS, web fonts, or JavaScript, use Grover (Puppeteer/Chromium) instead. A managed Chrome API such as html2img removes browser packaging. The right choice depends on rendering fidelity, deployment constraints, privacy, and how much output control you need.

Choose the rendering path first

Approach Rendering engine Best fit Deployment and access Important trade-off
IMGKit + wkhtmltoimage WebKit-based wkhtmltoimage Simple local HTML/CSS conversion Ruby gem plus a wkhtmltoimage binary Its browser behavior can differ from current Chrome, especially for modern CSS and JavaScript
Grover Google Puppeteer/Chromium Chrome-level layout, JavaScript, and web-font rendering Ruby gem with Chromium/Puppeteer packaging More browser runtime and deployment work
html2img Ruby client Managed real Chrome Hosted rendering without packaging Chromium API key and network access; the gem has zero runtime dependencies HTML is sent to a service and usage is governed by the account allowance

There are no independent speed or image-quality benchmarks in the available documentation, so treat these as architectural differences rather than performance rankings.

Option 1: Convert HTML with IMGKit and wkhtmltoimage

IMGKit describes itself as creating JPGs from “plain old HTML+CSS.” It supports JPEG, JPG, and PNG output and can render an HTML string, URL, or file. The following example writes a JPEG directly.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install the gem and renderer

  1. Add imgkit to your Gemfile and run bundle install, or install it with gem install imgkit.
  2. Install the wkhtmltoimage executable on the host, or add the wkhtmltoimage-binary gem as your project’s packaging method.
  3. Verify that the binary is available to the process that runs Ruby.

If the executable is not on the normal PATH, configure its location explicitly:

#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
IMGKit.configure do |config|
  config.wkhtmltoimage = "/opt/wkhtmltox/bin/wkhtmltoimage"
end

Render an HTML string to JPEG bytes

require "imgkit"

html = <<~HTML
  <!doctype html>
  <html>
    <head>
      <meta charset="utf-8">
      <style>
        body { margin: 0; font-family: Arial, sans-serif; background: #f4f6f8; }
        .card { width: 800px; padding: 32px; background: white; color: #18212b; }
        h1 { margin-top: 0; }
      </style>
    </head>
    <body>
      <main class="card">
        <h1>Ruby HTML capture</h1>
        <p>This document is rendered locally.</p>
      </main>
    </body>
  </html>
HTML

kit = IMGKit.new(html, quality: 50)
image_blob = kit.to_img(:jpeg)
File.binwrite("output.jpg", image_blob)

# The convenience method writes the file itself:
kit.to_file("output-2.jpg")

quality: 50 is an example setting, not a universal optimum. Test the quality that preserves your text and images at the intended display size. IMGKit also accepts a URL or local file when the content is not generated as a string.

When IMGKit is the right choice

  • Your HTML uses broadly supported CSS and does not depend on current browser APIs.
  • You want a self-contained, local pipeline and can install a system binary.
  • Your input is trusted or you have an explicit policy for loading remote resources.

If a page looks different from Chrome, that is a rendering-engine limitation rather than a JPEG-writing error. Move to a Chromium-based option when fidelity matters more than the smaller setup.

Option 2: Use Grover for Chromium rendering

Grover’s RubyGems description is “Transform HTML into PDF/PNG/JPEG using Google Puppeteer/Chromium.” It is the better fit when the result depends on current Chrome CSS behavior, JavaScript execution, or web fonts. Grover 1.2.4 was published on November 4, 2025 and requires Ruby >= 3.0.0, < 3.5.0; check those constraints against your deployed Ruby version before adopting it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Basic setup

  1. Add the grover gem to your Gemfile and run bundle install.
  2. Install or make available the Chromium/Puppeteer runtime required by your Grover installation.
  3. Render your HTML through Grover and select JPEG output using the version’s documented API.

A minimal application pattern is:

require "grover"

html = <<~HTML
  <!doctype html>
  <html>
    <head>
      <meta charset="utf-8">
      <style>body { margin: 0; font-family: system-ui, sans-serif; }</style>
    </head>
    <body><h1>Chromium-rendered HTML</h1></body>
  </html>
HTML

# Grover's release-specific API should be checked in its documentation.
# The resulting JPEG bytes can then be written with File.binwrite.
image = Grover.new(html).to_jpeg
File.binwrite("output.jpg", image)

Confirm the exact constructor and output method for the Grover version locked in your bundle; browser wrappers can change option names between releases. The key decision is the Chromium engine, not a particular JPEG quality number.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

Why Chromium can fix a WebKit mismatch

  • Modern CSS layout can follow the same engine family used by your users’ Chrome browsers.
  • Client-side JavaScript can run before capture, allowing the page to build its final DOM.
  • Web fonts can be loaded by the browser rather than approximated by a different renderer.

Chromium also increases operational surface area: the executable must be present, launch permissions must be correct, and a server process needs enough memory and time for browser startup and page loading.

Option 3: Render through the html2img Ruby client

The html2img client documentation says every render runs in real Chrome. Its HTML endpoint accepts a complete document and returns an image URL, while the Ruby gem has zero runtime dependencies. This is useful when you prefer a hosted browser over installing wkhtmltoimage or Chromium in each deployment environment.

Account and security requirements

  • An API key is required.
  • The documentation states that each account starts with 50 free credits.
  • Free-tier renders are hosted for seven days.
  • Keep the key on your server; do not embed it in browser-delivered JavaScript or public HTML.

Because the endpoint returns an image URL, your application must decide whether to download the image immediately, store it, or pass the URL to another service. Review the provider’s current client documentation for the exact Ruby method names and endpoint parameters before pinning an implementation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

JPEG output: quality, dimensions, and transparency

JPEG is a lossy format. It is commonly useful for photographic content or compact full-page captures. PNG is usually the safer choice for crisp text edges, flat interface colors, or transparency; both IMGKit and Grover document PNG alongside JPEG. No authoritative benchmark establishes a universal file-size or quality advantage, so compare representative pages from your own workload.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.

Control the input before conversion

  • Set an explicit viewport or content width in the renderer so responsive breakpoints are deterministic.
  • Use print-safe CSS only when your selected renderer applies it as expected.
  • Wait for remote fonts and images before capturing; otherwise the screenshot can contain fallback fonts or empty image boxes.
  • Keep a stable HTML snapshot for reproducible output. Dynamic timestamps, advertisements, and animations can change pixels between runs.

Neither JPEG nor PNG can repair a page that was captured before its JavaScript finished building the content. Rendering readiness belongs in the browser configuration or in the page itself.

Ruby implementation checklist

  1. Define the source. Decide whether Ruby receives a complete HTML string, reads a file, or navigates to a URL.
  2. Choose the engine. Select IMGKit for a simple WebKit pipeline, Grover for Chromium fidelity, or html2img for managed Chrome.
  3. Make dependencies explicit. Package the binary or browser runtime in deployment documentation and verify it in the same user account that runs the job.
  4. Make rendering deterministic. Set dimensions, include required CSS, and wait for assets and JavaScript.
  5. Write binary data correctly. Use File.binwrite or open the destination with binary mode; do not treat JPEG bytes as UTF-8 text.
  6. Validate the result. Check that the file exists, has a nonzero size, and opens as an image before publishing it.
  7. Protect untrusted input. A renderer that can fetch URLs or execute JavaScript should run with a least-privilege account and an egress policy appropriate to your application.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. It accepts one GET request and returns PNG, JPEG, WebP, or PDF. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.

The API supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, device presets or custom viewports, retina scale, custom CSS and JavaScript, click-before-capture actions, waits for selectors, delays or network idle, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Existing parameter names used by other screenshot APIs also work, easing migration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Ruby call

require "net/http"
require "uri"

uri = URI("https://api.screenshotneo.com/v1/shot")
uri.query = URI.encode_www_form(
  access_key: "YOUR_API_KEY",
  url: "https://stripe.com"
)
response = Net::HTTP.get_response(uri)
raise "Screenshot failed: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
File.binwrite("shot.webp", response.body)

See the ScreenshotNeo documentation for parameters and response headers. The same request in cURL is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
require('fs').writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting Ruby HTML-to-JPEG jobs

“No wkhtmltoimage executable found”

The gem is installed but the binary is missing or not on PATH. Install wkhtmltoimage, use the binary gem, or set IMGKit.configure to the absolute executable path. Test under the same service account used in production.

The JPEG is blank or only partly rendered

Check that the source URL is reachable from the rendering host and that the page does not require a blocked login, cookie, or network resource. For JavaScript-heavy pages, use a Chromium path and wait for the page’s final state before capture.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fonts or layout differ from the browser

This usually indicates an engine or font-loading difference. Compare IMGKit’s WebKit output with Grover’s Chromium output, embed or reliably serve the required fonts, and fix the viewport so responsive CSS selects the intended breakpoint.

The Ruby process cannot launch Chromium

Check Ruby compatibility, executable permissions, sandbox policy, and the browser runtime installation. Keep the Grover version and browser setup aligned in the deployment image rather than relying on an untracked system installation.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

The output file is corrupt

Write the response in binary mode and inspect the HTTP status before saving it. With a hosted API, an error response may be HTML or JSON rather than image bytes; do not save it as .jpg without checking.

Which option should you use?

  • Use IMGKit when local execution and a straightforward HTML/CSS feature set matter most.
  • Use Grover when current Chrome behavior, JavaScript, or web fonts determine correctness and you can operate Chromium.
  • Use html2img when a managed real-Chrome service is acceptable and you want a Ruby client without runtime dependencies.
  • Use ScreenshotNeo when you want a single API call, consent and popup cleanup, usage-aware billing, and an MCP route for AI agents.

Frequently Asked Questions

Can Ruby convert a local HTML file directly?

Yes. IMGKit can load a file as its input, or you can read the file into a Ruby string and pass that string to IMGKit.new before calling to_img(:jpeg).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does converting to JPEG execute JavaScript?

It depends on the renderer. A WebKit-based IMGKit pipeline may not match a current browser, while Chromium-based Grover and managed Chrome services are intended for browser-rendered pages; configure an explicit readiness condition for dynamic content.

Should I keep the intermediate image bytes in memory?

For small images, returning bytes and using File.binwrite is simple. For large or concurrent jobs, stream or store results according to your application’s memory and retention limits.

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.