Capture LogoCapture

Hash Generation Guide

Master MD5 hash generation for Capture API authentication. Step-by-step guide with code examples in JavaScript, Python, PHP, and Ruby for secure request signing.

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

On this page