Skip to main content

Hash Generation Guide

Understanding how to generate the required MD5 hash is essential for using Capture API. The hash serves as a security mechanism to authenticate your requests and prevent unauthorized usage.

How Hash Generation Works

The Capture API uses MD5 hashing to verify that requests are coming from authenticated users. The hash is generated by combining your API secret with the request URL and parameters.

Basic Formula

MD5(API_SECRET + REQUEST_URL_WITH_PARAMETERS)

URL Structure

All Capture API requests follow this structure:

https://cdn.capture.page/{API_KEY}/{GENERATED_HASH}/{ENDPOINT}?url={TARGET_URL}&{PARAMETERS}

Components:

  • {API_KEY}: Your API key from the console
  • {GENERATED_HASH}: MD5 hash you generate
  • {ENDPOINT}: API endpoint (image, pdf, content, metadata, animated)
  • {TARGET_URL}: The website URL you want to capture
  • {PARAMETERS}: Optional parameters for customization

Step-by-Step Process

1. Prepare the Hash Input

The hash input consists of:

API_SECRET + 'url=' + TARGET_URL + '&' + PARAMETERS

2. Generate MD5 Hash

Create an MD5 hash of the complete string from step 1.

3. Construct Final URL

Use the hash in your API request URL.

Language-Specific Examples

JavaScript/Node.js

const crypto = require('crypto');

function generateCaptureURL(apiKey, apiSecret, targetUrl, endpoint = 'image', params = {}) {
// Build parameter string
const paramString = Object.keys(params)
.map(key => `${key}=${encodeURIComponent(params[key])}`)
.join('&');

// Create hash input
const hashInput = apiSecret + 'url=' + encodeURIComponent(targetUrl) +
(paramString ? '&' + paramString : '');

// Generate MD5 hash
const hash = crypto.createHash('md5').update(hashInput).digest('hex');

// Construct final URL
const finalUrl = `https://cdn.capture.page/${apiKey}/${hash}/${endpoint}?url=${encodeURIComponent(targetUrl)}` +
(paramString ? '&' + paramString : '');

return finalUrl;
}

// Example usage
const apiKey = 'your-api-key';
const apiSecret = 'your-api-secret';
const targetUrl = 'https://example.com';

// Simple screenshot
const screenshotUrl = generateCaptureURL(apiKey, apiSecret, targetUrl, 'image');
console.log(screenshotUrl);

// Screenshot with parameters
const advancedUrl = generateCaptureURL(apiKey, apiSecret, targetUrl, 'image', {
vw: 1920,
vh: 1080,
format: 'png',
delay: 2
});
console.log(advancedUrl);

Python

import hashlib
import urllib.parse

def generate_capture_url(api_key, api_secret, target_url, endpoint='image', params=None):
if params is None:
params = {}

# Build parameter string
param_string = '&'.join([f"{key}={urllib.parse.quote_plus(str(value))}"
for key, value in params.items()])

# Create hash input
hash_input = (api_secret + 'url=' + urllib.parse.quote_plus(target_url) +
('&' + param_string if param_string else ''))

# Generate MD5 hash
hash_value = hashlib.md5(hash_input.encode()).hexdigest()

# Construct final URL
final_url = (f"https://cdn.capture.page/{api_key}/{hash_value}/{endpoint}"
f"?url={urllib.parse.quote_plus(target_url)}")

if param_string:
final_url += '&' + param_string

return final_url

# Example usage
api_key = 'your-api-key'
api_secret = 'your-api-secret'
target_url = 'https://example.com'

# Simple screenshot
screenshot_url = generate_capture_url(api_key, api_secret, target_url, 'image')
print(screenshot_url)

# PDF with parameters
pdf_url = generate_capture_url(api_key, api_secret, target_url, 'pdf', {
'format': 'A4',
'landscape': 'true',
'delay': 3
})
print(pdf_url)

PHP

<?php
function generateCaptureURL($apiKey, $apiSecret, $targetUrl, $endpoint = 'image', $params = []) {
// Build parameter string
$paramString = '';
if (!empty($params)) {
$paramPairs = [];
foreach ($params as $key => $value) {
$paramPairs[] = $key . '=' . urlencode($value);
}
$paramString = implode('&', $paramPairs);
}

// Create hash input
$hashInput = $apiSecret . 'url=' . urlencode($targetUrl) .
($paramString ? '&' . $paramString : '');

// Generate MD5 hash
$hash = md5($hashInput);

// Construct final URL
$finalUrl = "https://cdn.capture.page/{$apiKey}/{$hash}/{$endpoint}?url=" . urlencode($targetUrl);

if ($paramString) {
$finalUrl .= '&' . $paramString;
}

return $finalUrl;
}

// Example usage
$apiKey = 'your-api-key';
$apiSecret = 'your-api-secret';
$targetUrl = 'https://example.com';

// Simple screenshot
$screenshotUrl = generateCaptureURL($apiKey, $apiSecret, $targetUrl, 'image');
echo $screenshotUrl . "\n";

// Advanced screenshot
$advancedUrl = generateCaptureURL($apiKey, $apiSecret, $targetUrl, 'image', [
'vw' => 1920,
'vh' => 1080,
'darkMode' => 'true',
'blockAds' => 'true'
]);
echo $advancedUrl . "\n";
?>

Go

package main

import (
"crypto/md5"
"fmt"
"net/url"
"strings"
)

func generateCaptureURL(apiKey, apiSecret, targetURL, endpoint string, params map[string]string) string {
// Build parameter string
var paramPairs []string
for key, value := range params {
paramPairs = append(paramPairs, fmt.Sprintf("%s=%s", key, url.QueryEscape(value)))
}
paramString := strings.Join(paramPairs, "&")

// Create hash input
hashInput := apiSecret + "url=" + url.QueryEscape(targetURL)
if paramString != "" {
hashInput += "&" + paramString
}

// Generate MD5 hash
hash := fmt.Sprintf("%x", md5.Sum([]byte(hashInput)))

// Construct final URL
finalURL := fmt.Sprintf("https://cdn.capture.page/%s/%s/%s?url=%s",
apiKey, hash, endpoint, url.QueryEscape(targetURL))

if paramString != "" {
finalURL += "&" + paramString
}

return finalURL
}

func main() {
apiKey := "your-api-key"
apiSecret := "your-api-secret"
targetURL := "https://example.com"

// Simple screenshot
screenshotURL := generateCaptureURL(apiKey, apiSecret, targetURL, "image", nil)
fmt.Println(screenshotURL)

// Screenshot with parameters
params := map[string]string{
"vw": "1920",
"vh": "1080",
"format": "png",
"delay": "2",
}
advancedURL := generateCaptureURL(apiKey, apiSecret, targetURL, "image", params)
fmt.Println(advancedURL)
}

Rust

use std::collections::HashMap;

fn generate_capture_url(
api_key: &str,
api_secret: &str,
target_url: &str,
endpoint: &str,
params: Option<HashMap<String, String>>,
) -> String {
// Build parameter string
let param_string = if let Some(params) = params {
params
.iter()
.map(|(key, value)| format!("{}={}", key, urlencoding::encode(value)))
.collect::<Vec<_>>()
.join("&")
} else {
String::new()
};

// Create hash input
let mut hash_input = format!("{}url={}", api_secret, urlencoding::encode(target_url));
if !param_string.is_empty() {
hash_input.push('&');
hash_input.push_str(&param_string);
}

// Generate MD5 hash
let hash = format!("{:x}", md5::compute(hash_input.as_bytes()));

// Construct final URL
let mut final_url = format!(
"https://cdn.capture.page/{}/{}/{}?url={}",
api_key,
hash,
endpoint,
urlencoding::encode(target_url)
);

if !param_string.is_empty() {
final_url.push('&');
final_url.push_str(&param_string);
}

final_url
}

fn main() {
let api_key = "your-api-key";
let api_secret = "your-api-secret";
let target_url = "https://example.com";

// Simple screenshot
let screenshot_url = generate_capture_url(api_key, api_secret, target_url, "image", None);
println!("{}", screenshot_url);

// Screenshot with parameters
let mut params = HashMap::new();
params.insert("vw".to_string(), "1920".to_string());
params.insert("vh".to_string(), "1080".to_string());
params.insert("format".to_string(), "png".to_string());

let advanced_url = generate_capture_url(api_key, api_secret, target_url, "image", Some(params));
println!("{}", advanced_url);
}

Ruby

require 'digest'
require 'uri'

def generate_capture_url(api_key, api_secret, target_url, endpoint = 'image', params = {})
# Build parameter string
param_string = params.map { |key, value| "#{key}=#{URI.encode_www_form_component(value.to_s)}" }.join('&')

# Create hash input
hash_input = api_secret + 'url=' + URI.encode_www_form_component(target_url)
hash_input += '&' + param_string unless param_string.empty?

# Generate MD5 hash
hash = Digest::MD5.hexdigest(hash_input)

# Construct final URL
final_url = "https://cdn.capture.page/#{api_key}/#{hash}/#{endpoint}?url=#{URI.encode_www_form_component(target_url)}"
final_url += '&' + param_string unless param_string.empty?

final_url
end

# Example usage
api_key = 'your-api-key'
api_secret = 'your-api-secret'
target_url = 'https://example.com'

# Simple screenshot
screenshot_url = generate_capture_url(api_key, api_secret, target_url, 'image')
puts screenshot_url

# PDF with parameters
pdf_url = generate_capture_url(api_key, api_secret, target_url, 'pdf', {
format: 'A4',
landscape: true,
delay: 3
})
puts pdf_url

Common Examples

Screenshot Examples

Basic Screenshot

// Hash input: api_secret + 'url=https://example.com'
const hashInput = 'your-api-secret' + 'url=https://example.com';
const hash = crypto.createHash('md5').update(hashInput).digest('hex');
// URL: https://cdn.capture.page/your-api-key/{hash}/image?url=https://example.com

Screenshot with Viewport

// Hash input: api_secret + 'url=https://example.com&vw=1920&vh=1080'
const hashInput = 'your-api-secret' + 'url=https://example.com&vw=1920&vh=1080';
const hash = crypto.createHash('md5').update(hashInput).digest('hex');
// URL: https://cdn.capture.page/your-api-key/{hash}/image?url=https://example.com&vw=1920&vh=1080

Mobile Screenshot

// Hash input: api_secret + 'url=https://example.com&emulateDevice=iphone_15_pro'
const hashInput = 'your-api-secret' + 'url=https://example.com&emulateDevice=iphone_15_pro';
const hash = crypto.createHash('md5').update(hashInput).digest('hex');

PDF Examples

Basic PDF

// Hash input: api_secret + 'url=https://example.com'
const hashInput = 'your-api-secret' + 'url=https://example.com';
const hash = crypto.createHash('md5').update(hashInput).digest('hex');
// URL: https://cdn.capture.page/your-api-key/{hash}/pdf?url=https://example.com

PDF with Custom Format

// Hash input: api_secret + 'url=https://example.com&format=A4&landscape=true'
const hashInput = 'your-api-secret' + 'url=https://example.com&format=A4&landscape=true';
const hash = crypto.createHash('md5').update(hashInput).digest('hex');

Content & Metadata Examples

Content Extraction

// Hash input: api_secret + 'url=https://example.com'
const hashInput = 'your-api-secret' + 'url=https://example.com';
const hash = crypto.createHash('md5').update(hashInput).digest('hex');
// URL: https://cdn.capture.page/your-api-key/{hash}/content?url=https://example.com

Metadata with Delay

// Hash input: api_secret + 'url=https://example.com&delay=3'
const hashInput = 'your-api-secret' + 'url=https://example.com&delay=3';
const hash = crypto.createHash('md5').update(hashInput).digest('hex');

Important Considerations

1. Parameter Order

The order of parameters in your hash input must match the order in your final URL:

// ✅ Correct - same order
// Hash: api_secret + 'url=example.com&vw=1920&vh=1080'
// URL: .../image?url=example.com&vw=1920&vh=1080

// ❌ Incorrect - different order
// Hash: api_secret + 'url=example.com&vw=1920&vh=1080'
// URL: .../image?url=example.com&vh=1080&vw=1920

2. URL Encoding

Always URL-encode parameter values consistently:

// ✅ Correct - URL encode special characters
const targetUrl = 'https://example.com/page?id=123&ref=test';
const encodedUrl = encodeURIComponent(targetUrl);
const hashInput = apiSecret + 'url=' + encodedUrl;

3. Boolean Parameters

Convert boolean values to strings:

// ✅ Correct
const params = {
darkMode: 'true',
blockAds: 'false'
};

// ❌ Incorrect
const params = {
darkMode: true,
blockAds: false
};

4. Empty Parameters

Exclude parameters with empty or undefined values:

// ✅ Correct - filter out empty values
const params = { vw: 1920, vh: '', delay: 3 };
const validParams = Object.fromEntries(
Object.entries(params).filter(([_, value]) => value !== '' && value != null)
);

Security Best Practices

1. Keep API Secret Secure

  • Never expose API secret in client-side code
  • Use environment variables for secrets
  • Rotate secrets periodically

2. Server-Side Hash Generation

// ✅ Server-side (secure)
app.get('/generate-url', (req, res) => {
const hash = generateHash(API_SECRET, req.query.url, req.query.params);
res.json({ url: constructURL(API_KEY, hash, req.query.url, req.query.params) });
});

// ❌ Client-side (insecure)
const hash = generateHash(API_SECRET, url, params); // Exposes secret!

3. Validate Inputs

Always validate and sanitize inputs before hash generation:

function validateParams(params) {
const allowedParams = ['vw', 'vh', 'format', 'delay', 'darkMode'];
return Object.fromEntries(
Object.entries(params).filter(([key]) => allowedParams.includes(key))
);
}

Debugging Hash Issues

Common Problems

1. Hash Mismatch

Error: Invalid hash

Solution: Verify hash input matches URL parameters exactly.

2. URL Encoding Issues

// Debug: Print hash input
console.log('Hash input:', hashInput);
console.log('Generated hash:', hash);
console.log('Final URL:', finalUrl);

3. Parameter Order Problems

// Use consistent parameter ordering
function sortParams(params) {
return Object.keys(params).sort().reduce((sorted, key) => {
sorted[key] = params[key];
return sorted;
}, {});
}

Testing Hash Generation

function testHashGeneration() {
const apiSecret = 'test-secret';
const testCases = [
{
url: 'https://example.com',
params: {},
expected: 'url=https://example.com'
},
{
url: 'https://example.com',
params: { vw: 1920, vh: 1080 },
expected: 'url=https://example.com&vw=1920&vh=1080'
}
];

testCases.forEach((test, index) => {
const hashInput = apiSecret + test.expected;
const hash = crypto.createHash('md5').update(hashInput).digest('hex');
console.log(`Test ${index + 1}: ${hash}`);
});
}

Online Hash Generator

For quick testing, you can use online MD5 generators:

  1. Construct your hash input string
  2. Paste into an MD5 generator (e.g., md5hashgenerator.com)
  3. Use the resulting hash in your URL

Example:

  • Hash input: your-api-secreturl=https://example.com&vw=1920&vh=1080
  • MD5 result: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
  • Final URL: https://cdn.capture.page/your-api-key/a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6/image?url=https://example.com&vw=1920&vh=1080

See Also