We’re excited to introduce a new feature to our API: Certified Screenshots. This enhancement provides cryptographic proof that a screenshot was taken with a specific set of options at a given time, giving more authenticity and integrity to your renders.
Why is this useful?
Whether it's for regulatory archiving, brand monitoring, or digital forensics, this provides more authentic, trustworthy immutable web content. Here are some concrete use cases:
- Regulatory Compliance – You may need to prove you displayed certain policies, disclosures, or terms at a specific time.
- Preserving Online Content – Articles, social media posts, or public statements may be deleted or altered; a certified render ensures the truth remains captured.
- Monitoring Competitor Activity – You can track and preserve changes to websites for compliance or legal disputes.
How It Works
When you make a render request, add certify: true
to your options. In response, we return all the values we did before, plus:
- A timestamp of when your screenshot was taken.
- A cryptographic hash of the options, the rendered file, and the timestamp.
- The options used in the hash (these may differ slightly from your inputted options).
Storing these three allow you to verify the integrity of the screenshot at any time.
Some of the options you provide may generate additional options automatically. This is why the hashed options might differ slightly from what you originally submitted.
For example, we’ve recently updated Urlbox to use pre-signed URLs by default when storing renders in S3, to enhance security. When you include use_s3=true
, we generate a s3_presigned_url
—a derived option that becomes part of your final configuration.
Rest assured, using S3 and certified renders is just as safe. Pre-signed URLs are intentionally ephemeral, meaning they expire after a short time. Even if someone gained access to your hash and could decode it, the pre-signed URL would likely have already expired, making it useless for uploading to your S3 bucket.
Note - This approach works with all render formats—except for video formats and when using html=<h1>Hello World!</h1>
instead of a url=https://example.com
. It is not compatible with options that significantly alter the page’s structure or content, as that goes against the nature of this feature. Additionally, any options that might contain sensitive information are not compatible, to ensure privacy and security (except for use_s3
).
To confirm that a screenshot hasn't been altered, you can:
- Take the
file
, thetimestamp
, and the returnedhashedOptions
and concatenate them together with a period between each one e.g."{file}.{timestamp}.{hashedOptions}"
. - Hash the concatenated string using the sha256 hashing algorithm.
- Compare the hash to the one provided by our API response.
- If the hashes match, the screenshot is verified as authentic and unaltered.
Example
You can make a request using your favoured method. Here's an example with Curl and Postman:
curl --location 'https://api.urlbox.com/v1/render/sync' \
--header 'Authorization: Bearer {{YOUR_URLBOX_SECRET_HERE}}' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://theWebsiteYouWantToRender.com",
"certify": true
}'
The returned JSON should look familiar, with the addition of the certifiedHash
, timestamp
and hashedOptions
:
{
"renderUrl":"https://yourStorageLocation/yourRender.pdf",
"size": 297573,
"timestamp": "Mon, 17 Mar 2025 10:30:25 GMT",
"certifiedHash": "b64b8...",
"hashedOptions": {
"url": "https://theWebsiteYouWantToRender.com",
"certify": true
}
}
To verify this, we recommend using a callable script for manual verification, to simplify the process for you. Feel free to write your own code which performs the steps above.
The example below is based on a macOS/Linux environment with a shell script. Most hashing tools compatible with the sha256 algorithm should also work.
Steps to verify:
- Copy the below, save it as
verify.sh
. - Give it permission to run by executing
chmod +x verify.sh
in the command line. - Ensure you've got jq available for JSON formatting.
- Take the
renderUrl
from the JSON response you received earlier, and save that render locally. - Run
./verify.sh /path/to/the/downloaded/file.pdf
in the command line.
You'll be prompted for the JSON response from the API. Paste it with Ctrl+V and hit Ctrl+D twice to confirm.
The response should show you the computed hash from the shell script, the certified hash from the JSON response, and whether they matched. If they match, then you have a certified screenshot!
#!/bin/bash
# Check that we passed in the downloaded file path
if [[ $# -lt 1 ]]; then
echo "Error: Missing local file path."
echo "Usage: ./verify.sh <localFilePath>"
exit 1
fi
FILE_PATH="$1"
# Ensure the file exists
if [[ ! -f "$FILE_PATH" ]]; then
echo "Error: File '$FILE_PATH' not found."
exit 1
fi
# Prompt to paste render response JSON
echo "Paste JSON payload and press Ctrl+D twice when done:"
JSON_INPUT=$(jq -nR '[inputs] | join("\n")' | jq -r '. | fromjson' 2>/dev/null)
# Validate the JSON
if [[ -z "$JSON_INPUT" || $(echo "$JSON_INPUT" | jq empty 2>&1) ]]; then
echo "Error: Invalid JSON provided."
exit 1
fi
# Extract values from the JSON
RENDER_TIMESTAMP=$(echo "$JSON_INPUT" | jq -r '.timestamp')
CERTIFIED_HASH=$(echo "$JSON_INPUT" | jq -r '.certifiedHash')
HASHED_OPTIONS_JSON=$(echo "$JSON_INPUT" | jq -cS '.hashedOptions')
# Compute SHA-256 hash of the file
BUFFER_HASH=$(shasum -a 256 "$FILE_PATH" | awk '{print $1}')
echo
echo "FILE: $FILE_PATH"
echo "BUFFER_HASH: $BUFFER_HASH"
echo "OPTIONS: $HASHED_OPTIONS_JSON"
echo "TIMESTAMP: $RENDER_TIMESTAMP"
echo
# Compute the final hash to compare against the certified hash
FINAL_HASH=$(echo -n "$BUFFER_HASH.$RENDER_TIMESTAMP.$HASHED_OPTIONS_JSON" | shasum -a 256 | awk '{print $1}')
# Compare hashes
MATCH_RESULT="false"
if [[ "$FINAL_HASH" == "$CERTIFIED_HASH" ]]; then
MATCH_RESULT="true"
fi
# Output results in JSON format
jq -n \
--arg computedHash "$FINAL_HASH" \
--arg certifiedHash "$CERTIFIED_HASH" \
--arg match "$MATCH_RESULT" \
'{computedHash: $computedHash, certifiedHash: $certifiedHash, match: $match}'
Here's what an example Terminal Execution should look like:
./verify.sh pdf.pdf
Paste JSON payload and press Ctrl+D twice when done:
{
"renderUrl": "https://someRenderUrl/file.pdf",
"size": 3966457,
"timestamp": "Mon, 17 Mar 2025 12:22:23 GMT",
"certifiedHash": "8b707...",
"hashedOptions": {
"url": "https://theWebsiteYouWantToRender.com",
"format": "pdf",
"certify": true
}
}
FILE: pdf.pdf
BUFFER_HASH: 5780000...
OPTIONS: {"certify":true,"format":"pdf","url":"https://theWebsiteYouWantToRender.com"}
TIMESTAMP: Mon, 17 Mar 2025 12:22:23 GMT
{
"computedHash": "8b707...",
"certifiedHash": "8b707...",
"match": "true"
}
Room to Improve
We recognize that while it adds a layer of integrity verification, there are potential weaknesses. If you require stronger authenticity guarantees please reach out to us. We’re open to feedback and eager to evolve this feature to meet higher authentication and legal standards.
Additionally, if you're struggling to get started, or to verify your renders, please do reach out to us.
Happy rendering!