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

To capture a page from a Remix app, submit the target URL to a screenshot service from a server-side action or loader, keep the API key in server-only configuration, then return or display the result. This guide uses Screenshot API’s documented REST endpoint in a Remix-style route; it is a REST adaptation, not a verified copy of the vendor’s unavailable Remix SDK example.

The code targets a Remix v2-style route module. Remix’s official documentation says, “The latest version of Remix is now React Router v7”; if your project uses React Router v7 framework mode, check its route conventions and response helpers before adopting the route code. Remix documentation

Choose a route: action or loader

Use an action when a person submits a form or presses a button to request a capture. It is a natural fit for a user-triggered operation and lets the browser submit the URL without calling the screenshot service directly. Use a loader when the screenshot is read as part of a route’s data, such as a preview page. Whether to cache that route response is an application decision; the screenshot service also has its own capture cache.

Screenshot API’s integration directory describes a Remix guide based on loaders and actions and recommends installing @screenshot-api/js. The linked guide’s detailed code was not available, so this tutorial does not assume SDK method names or result types. It calls the documented REST API directly, using server-side JavaScript fetch.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

Prepare the app and protect the API key

  1. Get an API key from Screenshot API and store it in a server-only environment variable, for example SCREENSHOT_API_KEY. Do not place it in a component, browser bundle, public environment variable, or form field.

  2. Ensure the variable is available to the process running your Remix server. For local development, use your project’s usual private environment-file workflow; for deployment, configure it in the hosting platform’s server environment.

  3. Use an authorization header. Screenshot API documents bearer-token authentication and recommends headers over its query-string convenience option.

The package name in the vendor’s integration listing is @screenshot-api/js, but the code below does not depend on that package. This avoids relying on unconfirmed SDK method names.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Build a server-side screenshot action

Create a route module such as app/routes/screenshot.tsx in a Remix v2-style app. The action accepts a form field named url, validates it, sends a JSON POST request, checks the upstream status, and returns the response data for the route component.

import { json, type ActionFunctionArgs } from "@remix-run/node";
import { Form, useActionData } from "@remix-run/react";

function isAllowedTarget(value: string): boolean {
  try {
    const parsed = new URL(value);
    return parsed.protocol === "https:" || parsed.protocol === "http:";
  } catch {
    return false;
  }
}

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const url = String(formData.get("url") ?? "").trim();

  if (!url || !isAllowedTarget(url)) {
    return json(
      { error: "Enter a valid HTTP or HTTPS URL." },
      { status: 400 },
    );
  }

  const apiKey = process.env.SCREENSHOT_API_KEY;
  if (!apiKey) {
    throw new Response("Screenshot service is not configured.", { status: 500 });
  }

  let upstream: Response;
  try {
    upstream = await fetch(
      "https://api.screenshot-api.org/api/v1/screenshot",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          url,
          viewport: { width: 1280, height: 720 },
          format: "png",
          fullPage: true,
        }),
        signal: AbortSignal.timeout(90_000),
      },
    );
  } catch {
    throw new Response("Could not reach the screenshot service.", { status: 502 });
  }

  const payload = await upstream.json().catch(() => null);
  if (!upstream.ok) {
    const status = upstream.status === 429 ? 429 : 502;
    return json(
      {
        error:
          payload?.error?.message ??
          payload?.message ??
          `Screenshot request failed (${upstream.status}).`,
      },
      { status },
    );
  }

  return json({ result: payload });
}

export default function ScreenshotRoute() {
  const data = useActionData<typeof action>();
  const result = data && "result" in data ? data.result : null;
  const screenshotUrl = result?.data?.screenshotUrl ?? result?.screenshotUrl;

  return (
    <main>
      <h1>Capture a website screenshot</h1>
      <Form method="post">
        <label htmlFor="url">Page URL</label>
        <input id="url" name="url" type="url" required />
        <button type="submit">Capture screenshot</button>
      </Form>
      {data && "error" in data ? <p role="alert">{data.error}</p> : null}
      {screenshotUrl ? (
        <figure>
          <img src={screenshotUrl} alt="Captured website" />
          <p><a href={screenshotUrl}>Open screenshot</a></p>
        </figure>
      ) : null}
    </main>
  );
}

This example deliberately accepts only HTTP and HTTPS schemes, but that check alone is not a complete defense when users can submit arbitrary destinations. In a public application, restrict destinations to an allowlist where possible and apply your hosting environment’s protections against server-side request forgery, including access to private network addresses and cloud metadata services. Also consider limiting request size, user access, and capture frequency.

Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

The vendor’s JavaScript examples do not use one identical JSON access pattern: one reads data.screenshotUrl, while another destructures { data }. The route therefore checks both commonly shown locations. Confirm the actual successful response shape from your account’s current API response and tighten the type and parsing accordingly; do not treat an assumed JSON field as guaranteed.

Return a URL, bytes, or a redirect

The route above returns JSON to the Remix component and displays the URL received from the upstream response. This is convenient for a preview interface, but it relies on the screenshot URL being suitable for the browser to load. For private images or stricter access control, have your server fetch and stream the artifact to the client instead, using the content type returned by the service and setting appropriate cache headers. Avoid blindly proxying arbitrary upstream URLs; validate the host and response size.

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.

Screenshot API returns JSON by default. Its REST documentation also describes a GET option redirect=1 that redirects to the image or PDF URL. That behavior can suit a direct-link endpoint, but the POST request shown here is preferable when you need advanced capture settings in a JSON body.

Adjust capture options for the page

The POST endpoint accepts a target url; the documented default format is PNG and fullPage defaults to false. The example explicitly chooses a 1280 × 720 viewport, PNG, and full-page capture so the result is predictable. Add only controls your route actually needs.

Need Option or behavior When to use it
Control the layout viewport width and height; deviceScaleFactor Choose desktop, tablet, or mobile dimensions. Use device scale factor to control output scaling.
Capture output type format: PNG, JPEG, WebP, or PDF PNG is the default. quality applies to JPEG and WebP. PDF-specific controls require format: "pdf".
Capture a long page fullPage: true Captures the full scrollable page rather than only the viewport.
Wait for content waitUntil, waitForSelector, delayMs Use a readiness condition or a delay when content appears after initial navigation. Documented waitUntil values are load, domcontentloaded, networkidle0, and networkidle2; the documented default is networkidle2.
Capture one element selector Target a CSS-selected element instead of the whole page. Element capture is not supported for PDF; use waitForSelector when the target appears late.
Clean or change appearance blockAds, blockCookieBanners, darkMode The first two default to true and dark mode defaults to false. POST can also inject css or js, or remove matching hideSelectors.
Render a regional view Geolocation, timezone, locale Use these POST options when page content or formatting depends on regional context.
Reuse captures cache, cacheTTL, staleTTL Documented defaults are cache enabled, a 86400-second cache TTL, and a 43200-second stale TTL. Defaults are service behavior, not a promise that every request returns a fresh capture.

Capture a specific element

Set selector to a CSS selector for the element you need, for example main article, and set waitForSelector to that selector if it may render after navigation. This can reduce irrelevant page content in a screenshot. It does not apply to PDF output, so choose an image format for selector-based captures.

Wait for dynamic content without waiting forever

Use waitUntil to choose a navigation milestone, then add waitForSelector or a modest delayMs only if the page needs it. Pages with persistent network connections may not become idle promptly, while a short delay can miss late content. Tune the wait for the target page and handle render failures rather than assuming one setting fits every site.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.

Choose GET or POST

GET accepts basic query parameters. POST uses a JSON body and supports advanced options such as CSS or JavaScript injection, hidden selectors, geolocation, and PDF controls. For a Remix action with user-selected settings, POST keeps the options together and avoids exposing sensitive values in a URL.

Handle errors and limits in the UI

The API documents structured errors with these status and error categories. Use the response status to show a useful next step instead of presenting every failure as a generic blank preview.

API response Likely meaning Application response
401 unauthorized Credentials are missing, invalid, or not accepted. Show a service-configuration error to the user and check the server environment variable and authorization header in logs without logging the key.
400 invalid_request The request body or one of its values is invalid. Return a field-level message and verify the parameter names and value types sent by the route.
429 rate_limited or quota_exceeded The request rate or account allowance has been reached. Tell the user to retry later when appropriate; for repeated or quota-related errors, inspect account usage and response quota headers.
502 render_failed The service could not complete the page render. Check whether the URL is reachable, whether the site blocks automated access, and whether the selected wait condition or selector fits the page.
422 selector_not_found The requested CSS selector was not found. Verify the selector against the rendered page and use a wait condition if the element is inserted late.

When checked in the vendor API docs, the free plan is listed at 60 requests per minute and 500 screenshots per month. Those are vendor-documented limits and can change; check the live documentation and your account’s response headers before relying on them. The API docs describe rate and quota headers in responses.

Plan for performance, reliability, and cost

A screenshot request requires the service to load and render the target page, so response time depends on the page and capture settings as well as the API. Full-page capture, late-content waits, PDF generation, and complex pages can all make a request take longer than a simple viewport shot. Set a server-side timeout appropriate to your application, surface a pending state for long captures, and avoid launching duplicate requests when a user double-submits.

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

For interactive use, a synchronous action is straightforward, but it holds the request open until the capture completes. For larger workloads, Screenshot API documents a batch endpoint that accepts multiple URLs and returns a batch ID, with status and event-stream endpoints. That is a better shape for background processing than asking one web request to wait for a large set of captures.

Cost control starts with validating destinations and limiting who can request captures. Cache behavior is enabled by default in the API docs, with configurable TTLs; decide whether freshness or reuse matters more for your use case. Keep an eye on the service’s usage and quota headers, and do not automatically retry a 400, 401, 422, or 429 response as if it were a transient network failure.

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If you would rather not wire a browser-rendering service into a Remix route, ScreenshotNeo offers a one-GET screenshot API and an MCP server for AI agents. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status. Its MCP tools include take_screenshot, get_page_info, and capture_pdf.

Here is the cURL call; the API key stays in the request, so run it from your server or a trusted shell, not browser code. See the ScreenshotNeo API documentation for available options.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo also provides 1,000 screenshots a month free with no card; paid plans start at $5 for 3,000. Sign up for ScreenshotNeo free.

Troubleshooting the Remix integration

  • The browser reports an error, but the API key is set. Confirm the screenshot call runs only in the route module’s server-side action or loader. A browser-side call cannot safely read a server-only environment variable.

  • The route returns 500 because the key is missing. Check that SCREENSHOT_API_KEY is configured in the environment of the running server process, then restart the local server if needed. Do not expose the value in client configuration to make it available.

  • The action returns 400. Inspect the submitted form field name and target URL, then compare the JSON body with the API’s documented parameters. The sample only allows HTTP and HTTPS URLs; apply your own destination policy as well.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • The upstream response is not valid JSON. The sample attempts JSON parsing and reports a generic upstream status when parsing fails. Log the status and a safely truncated response body on the server for diagnosis, but do not send secrets or sensitive upstream details to end users.

    Best Value
    Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
    • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
    • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
    • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
    • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
    • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
  • A screenshot succeeds but the image does not render. Inspect the actual response shape and verify that the URL is available to the browser. If the artifact requires private access, proxy the bytes from a server route rather than embedding a URL the browser cannot fetch.

  • The image misses a menu, chart, or other late content. Make the page ready condition more specific with waitForSelector or add a suitable delay. Check the selector spelling and remember that selector element capture is unavailable for PDFs.

  • Captures fail intermittently or the app feels slow. Treat 502 render failures as capture failures, not successful empty images. Avoid aggressive automatic retries; log status, request duration, target host, and capture settings so you can distinguish a target-site problem from a route or quota issue.

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

When to use a hosted API or run your own browser

A hosted API avoids operating browser infrastructure yourself, while a self-hosted browser can offer more control over network access and the rendering environment. The trade-off is operational: with self-hosting, your team owns browser updates, concurrency, retries, output storage, and delivery; with a hosted service, you must work within its API behavior, quotas, and account terms. Choose based on your security boundary, workload, and operational capacity rather than assuming one approach is faster or cheaper in every case.

Frequently Asked Questions

Can a Remix loader call a screenshot API?

Yes. A loader can make a server-side request when screenshot data is part of route loading; use an action for a user-triggered form submission.

Does this example use Screenshot API’s official Remix SDK methods?

No. It uses the documented REST API from a Remix v2-style server route because the detailed vendor Remix SDK example could not be confirmed. The integration directory lists the package @screenshot-api/js, but this code does not depend on it.

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.

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