Free tools Windows power users keep installed
One-click scans. No signup required.
To receive a screenshot webhook in Node.js, expose a public HTTPS endpoint that accepts POST requests, preserve the request’s original body, verify it using the selected provider’s signature rules, and only then parse and process the event. The details are provider-specific: header names, secrets, signature encodings, callback availability, and acknowledgment requirements are not interchangeable.
What a screenshot webhook receiver does
A webhook lets a screenshot service send an HTTP POST to your application when an asynchronous render reaches a result. Your app supplies a callback URL with the screenshot request; the provider later calls that URL with an event payload. This is different from receiving the screenshot response directly in the request that started the render.
The endpoint must be reachable from the provider’s servers, accept POST, and return the acknowledgment expected by that provider. A successful response does not itself prove that a callback is authentic. Treat the URL as a delivery address, not as a password: verify the signature before trusting the contents.
First check that the exact API product and deployment you use currently supports callbacks. The guide for the Screenshot API at screenshotapis.org describes a webhook flow, but also says callbacks currently return 503 without charging a credit on its deployment and recommends synchronous rendering. In contrast, ScreenshotOne and ScreenshotMAX document asynchronous callback workflows. An example protocol in documentation is not proof that the feature is active for every deployment.
Recommended Free Tools
#1 Best Overall
- 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.
Provider differences that affect your Node.js code
Do not copy one provider’s signature header or secret into another provider’s integration. The documented conventions differ:
| Provider documentation | Callback and signature details | Acknowledgment or availability note |
|---|---|---|
| ScreenshotOne | Documents asynchronous requests using webhook_url. Its signature header is X-ScreenshotOne-Signature; verification uses HMAC-SHA256 and a secret key distinct from the API key. Its Node.js example reads the raw request text. |
Follow its current async and signature documentation for request details and expected response behavior. |
| ScreenshotMAX | Documents webhook_signed as an optional signed mode. When enabled, X-Screenshotmax-WebHook-Signature carries an HMAC-SHA256 signature generated with secret_key and the payload. Verification uses the exact raw JSON body. |
The callback URL must be publicly accessible over HTTP or HTTPS, accept POST, and return a 2xx status to acknowledge an event. |
| Screenshot API at screenshotapis.org | Its guide describes a webhook_url on screenshot or PDF requests and an X-Webhook-Signature HMAC-SHA256 hex digest of the JSON body signed with the API key. |
The guide says async callbacks currently return 503 without charging a credit on its deployment. Use synchronous rendering there unless current documentation says availability has changed. |
These are vendor-specific statements, not a shared webhook standard. Check the provider’s current documentation for exact header spelling, secret type, whether a signature prefix is included, digest encoding, callback activation, and acknowledgment contract before deploying.
Build a raw-body Express receiver
The following Express example shows the verification pattern documented for ScreenshotOne: retain the exact body bytes, calculate HMAC-SHA256 with the provider’s webhook secret, compare the signature without an ordinary string equality check, then parse JSON. It is not a universal drop-in integration. Confirm whether your chosen provider signs the raw bytes or text, how its header is encoded, and whether it prefixes the digest; adapt the marked provider-specific pieces accordingly.
Rank #2
- 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.
Install Express with npm install express. Save this as server.mjs and set SCREENSHOTONE_WEBHOOK_SECRET in the process environment to the provider’s webhook secret, not the API key:
import express from 'express';
import { createHmac, timingSafeEqual } from 'node:crypto';
const app = express();
const port = Number(process.env.PORT || 3000);
const webhookSecret = process.env.SCREENSHOTONE_WEBHOOK_SECRET;
if (!webhookSecret) {
throw new Error('Set SCREENSHOTONE_WEBHOOK_SECRET before starting the server');
}
function isValidScreenshotOneSignature(rawBody, headerValue) {
if (!headerValue) return false;
// Match this extraction and encoding to the provider's current specification.
const receivedHex = headerValue.trim();
if (!/^[a-f0-9]{64}$/i.test(receivedHex)) return false;
const expected = createHmac('sha256', webhookSecret)
.update(rawBody)
.digest();
const received = Buffer.from(receivedHex, 'hex');
return received.length === expected.length &&
timingSafeEqual(received, expected);
}
// Register this route before express.json(), so the body remains unparsed.
app.post('/webhooks/screenshot', express.raw({ type: 'application/json', limit: '1mb' }), async (req, res) => {
if (!Buffer.isBuffer(req.body)) {
return res.status(415).send('Expected application/json');
}
const signature = req.get('X-ScreenshotOne-Signature');
if (!isValidScreenshotOneSignature(req.body, signature)) {
return res.status(401).send('Invalid webhook signature');
}
let event;
try {
event = JSON.parse(req.body.toString('utf8'));
} catch {
return res.status(400).send('Invalid JSON');
}
// Check the event shape and expected render state before acting on it.
if (!event || typeof event !== 'object') {
return res.status(400).send('Unexpected event');
}
try {
// Replace with durable, idempotent work appropriate to your application.
console.log('Verified screenshot callback received');
return res.sendStatus(200);
} catch (error) {
console.error('Webhook processing failed');
return res.sendStatus(500);
}
});
app.listen(port, () => {
console.log(`Webhook receiver listening on port ${port}`);
});
In this example, the HMAC is calculated over the exact bytes Express received. The header is read after Express normalizes header access; HTTP header names are case-insensitive, so casing in the JavaScript accessor is not a separate security check. If the provider uses a prefix such as a named version, or a different encoding, parse that format exactly as its documentation specifies rather than silently stripping arbitrary text.
Why raw bytes must come first
Signature verification authenticates the bytes used to generate the signature. Parsing JSON and then serializing it again can change whitespace, key order, escaping, or line endings. The re-serialized text may represent equivalent JSON while producing a different digest. Keep the original request body and verify it before parsing.
Rank #3
- 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.
Keep middleware order deliberate
Do not run express.json() on this route before the raw-body parser. If the app uses JSON parsing for other routes, register the webhook route first, then add the general middleware afterward:
app.post('/webhooks/screenshot', express.raw({ type: 'application/json' }), webhookHandler);
app.use(express.json());
If a reverse proxy, hosting adapter, or framework has already consumed or transformed the request body, the bytes available in the handler may no longer match what the provider signed. Configure the runtime to preserve the raw body and test the production path, not just local Express.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Use the callback safely after verification
- Validate the payload. After signature verification and JSON parsing, check required identifiers, expected event type or render state, and any URL or job identifier your application expects. A valid signature proves the source according to that provider’s scheme; it does not mean every field matches your business logic.
- Make handling idempotent. Record a stable event or job identifier and avoid applying the same result twice. This is robust receiver design, not a claim that a particular provider retries or delivers duplicates.
- Keep the request handler short. For slow storage, image processing, or downstream calls, persist or enqueue the verified event and acknowledge once your chosen design has safely accepted responsibility for it. Do not return success before the event is durable if losing it would matter.
- Return the documented acknowledgment. ScreenshotMAX specifically calls for a 2xx response. For another provider, check its current requirements for response codes, timeout, and what counts as acknowledgment; those details are not established as common across providers.
- Protect sensitive data. Keep webhook secrets in environment-based secret storage, restrict access, rotate them if exposed, and do not log them. Avoid logging full payloads if they contain URLs, headers, or other sensitive values.
Do not infer retry behavior, ordering, or exactly-once delivery from the fact that a provider offers webhooks. The reviewed provider material does not establish a shared policy. Consult the selected provider’s current delivery documentation and make your system tolerate duplicate events where practical.
Rank #4
- 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
Test the endpoint before production
- Send a valid signed sample body through the same proxy and runtime path that production will use; confirm the signature passes and the handler returns the expected 2xx.
- Change one byte in the body and confirm verification fails before JSON processing or side effects.
- Send an invalid signature, malformed JSON, a missing signature header, and an unexpected event shape; confirm each is rejected safely.
- Confirm the endpoint is reachable over the public HTTP or HTTPS URL configured with the provider, rather than only from localhost.
- Check that your access logs do not expose the secret or sensitive request content and that a repeated event does not repeat irreversible work.
A local tunnel can help during development, but the public URL and behavior in the deployed environment still need verification. Ensure any gateway preserves the request body and forwards the signature header.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting common failures
- Every signature is invalid: Confirm the secret belongs to the webhook signing feature and the right environment. For ScreenshotOne, the signing secret is distinct from the API key. Check raw-body preservation, digest encoding, whitespace/prefix handling, and whether the provider expects bytes or text.
- The signature header appears missing: Confirm that the provider is configured to sign callbacks; ScreenshotMAX documents signed mode as optional. Check proxy rules and use the framework’s case-insensitive header getter rather than depending on one capitalization in a raw header map.
- JSON parsing fails or the body is empty: Ensure the raw parser matches the provider’s content type and runs before JSON middleware. Check request-size limits and whether an upstream adapter consumed the stream.
- The provider cannot reach the callback: Use a publicly accessible endpoint and verify DNS, TLS, firewall, routing, and POST handling. A localhost-only development server is not reachable from a remote service.
- The provider reports an unacknowledged event: Return the status code its documentation requires, and avoid waiting for long-running work in the request if that exceeds its delivery expectations. Timeout and retry specifics must be checked with the provider.
- Callbacks never arrive: Confirm async callbacks are currently enabled for the chosen product and deployment, that the request included the expected callback parameter, and that the job reached a callback-producing outcome. For screenshotapis.org, its guide currently states callbacks are unavailable on its deployment and return 503.
Or skip the browser setup
If your real goal is to get a screenshot rather than receive an asynchronous callback, ScreenshotNeo provides a screenshot API and MCP server for developers. Its one-request API returns an image or PDF; it is a different workflow from configuring a webhook receiver, so it does not replace callback handling when your application specifically needs provider POST events.
For example, this cURL request saves a screenshot of Stripe as WebP. See the ScreenshotNeo API documentation for parameters and response details:
Best Value
- 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.
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 banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are not billed. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000.
Learn about ScreenshotNeo, or sign up for 1,000 free screenshots a month with no card.
Frequently Asked Questions
Can I use one signature-verification function for every screenshot API?
No. Header name, secret type, signed bytes, prefix, and digest encoding depend on the provider. Implement and test against the selected provider’s current specification.
Does ScreenshotNeo provide the webhook receiver described here?
The ScreenshotNeo facts used here describe its screenshot API and MCP server, not a webhook callback contract. Use the API for direct screenshot capture; use the relevant provider’s webhook documentation when you need callback POSTs.
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.

