Privacy-RIP provides both client-side JavaScript APIs and server-side Python APIs for browser fingerprinting research. This document covers all available endpoints, configuration options, and integration methods.
Description: Main research interface
Purpose: Serves the interactive PRIP testing environment
Response:
<!-- Interactive HTML interface with real-time monitoring -->Example:
curl http://localhost:5000/Description: User reconnection endpoint
Purpose: Handles storage consistency validation and user tracking
Parameters:
u(int): User ID code indicating storage availabilityd(int): Device ID code indicating storage availability
Response:
{
"message": "User reconnection processed",
"timestamp": "2025-05-30T10:30:00Z",
"uid_code": 7,
"did_code": 7
}Example:
curl "http://localhost:5000/reconnect_user?u=7&d=7"UID/DID Code Values:
0: No storage available1: Only cookies available2: Only localStorage available3: Cookies + localStorage available4: Only sessionStorage available5: Cookies + sessionStorage available6: localStorage + sessionStorage available7: All storage types available
Description: Generate test data
Purpose: Creates sample fingerprinting data for testing
Response:
{
"status": "success",
"test_data_generated": true,
"timestamp": "2025-05-30T10:30:00Z",
"sample_fingerprint": {
"visitor_id": "abc123def456",
"user_agent": "Mozilla/5.0...",
"screen_resolution": [1920, 1080]
}
}Example:
curl -X POST http://localhost:5000/testDescription: Clear collected data
Purpose: Removes all stored research data
Response:
{
"status": "success",
"message": "All data cleared",
"timestamp": "2025-05-30T10:30:00Z"
}Example:
curl -X POST http://localhost:5000/clear_dataDescription: Process PRIP fingerprint data
Purpose: Accepts and processes browser fingerprinting data
Request Body:
{
"cookies": {
"data_a": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"data_b": "iOiJIUzI1NiIsInR5cCI6Ik...",
"PRIP_USERID": "123456789012",
"PRIP_USERDEVICE": "987654321098"
}
}Response:
{
"status": "success",
"processed": true,
"user_id": "123456789012",
"device_id": "987654321098",
"fingerprint_confidence": 0.95
}Example:
import requests
data = {
"cookies": {
"data_a": "base64_encoded_data...",
"PRIP_USERID": "123456789012"
}
}
response = requests.post("http://localhost:5000/api/data", json=data)
print(response.json())const prip = new PrivacyRipper(options);Options:
{
endpoint: '/reconnect_user', // Server endpoint URL
debug: false, // Enable debug logging
autoInit: true, // Automatically initialize
userDeviceLength: 12, // Device ID length
userIdLength: 12, // User ID length
reconnectMethod: 'GET', // HTTP method for reconnection
cookiePrefix: 'data_', // Prefix for data cookies
storagePrefix: 'PRIP_' // Prefix for storage keys
}Description: Generate unique device identifier
Returns: String (device ID)
const deviceId = prip.generateDeviceId();
console.log(deviceId); // "123456789012"Description: Generate unique user identifier
Returns: String (user ID)
const userId = prip.generateUserId();
console.log(userId); // "987654321098"Description: Collect comprehensive browser fingerprint
Returns: Promise (fingerprint data)
const fingerprint = await prip.collectFingerprint();
console.log(fingerprint);
/*
{
userAgent: "Mozilla/5.0...",
screenResolution: [1920, 1080],
colorDepth: 24,
hardwareConcurrency: 8,
// ... many more attributes
}
*/Description: Validate ID consistency across storage types
Returns: Object (consistency status)
const consistency = prip.checkStorageConsistency();
console.log(consistency);
/*
{
isConsistent: true,
userIdMatches: true,
deviceIdMatches: true,
storageTypes: ['cookie', 'localStorage', 'sessionStorage']
}
*/Description: Send reconnection request to server
Returns: Promise
const response = await prip.reconnectUser();
console.log(response);Description: Remove all PRIP data from browser
Returns: void
prip.clearAllData();<script src="P-RIP/PrivacyRipper.js"
data-prip-userdevice-length="16"
data-prip-userdevice-chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
data-prip-userid-length="20"
data-prip-userid-chars="abcdefghijklmnopqrstuvwxyz0123456789"
data-prip-reconnect-url="/api/user-reconnect"
data-prip-reconnect-method="POST"
data-prip-debug="true">
</script>window.PRIP_CONFIG = {
PRIP_USERDEVICE: {
length: 16,
randomChars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
},
PRIP_USERID: {
length: 20,
randomChars: 'abcdefghijklmnopqrstuvwxyz0123456789'
},
PRIP_RECONNECT: {
url: '/api/user-reconnect',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'your-api-key'
}
},
PRIP_DEBUG: true
};<meta name="prip-config" content='{"PRIP_RECONNECT":{"url":"/custom-endpoint","method":"POST"},"PRIP_DEBUG":true}'>Description: Extract and process PRIP data from Flask request
Parameters: Flask request object
Returns: Dictionary with extracted data
from Extractor import process_request
@app.route('/api/analyze', methods=['POST'])
def analyze_data():
try:
user_data = process_request(request)
return jsonify(user_data)
except ValueError as e:
return jsonify({"error": str(e)}), 400Description: Extract structured information from raw fingerprint data
Parameters:
user_data(dict): Raw fingerprint datauser_id(str): User identifierdevice_id(str): Device identifier
Returns: Structured dictionary with categorized data
from Extractor import user_info_extract
extracted = user_info_extract(raw_data, "user123", "device456")
print(extracted['system']['platform']) # "Win32"
print(extracted['webgl']['vendor']) # "NVIDIA Corporation"{
"timestamp": "2025-05-30T10:30:00Z",
"visitor_id": "abc123def456",
"user_id_from_cookie": "123456789012",
"device_id_from_cookie": "987654321098",
"confidence": 0.95,
"fingerprint": {
"canvas": {
"geometry_hash_sha256": "a1b2c3...",
"text_hash_sha256": "d4e5f6..."
},
"webgl": {
"version": "WebGL 2.0",
"vendor": "NVIDIA Corporation",
"renderer": "GeForce GTX 1060"
},
"system": {
"platform": "Win32",
"hardware_concurrency": 8,
"device_memory": 16
},
"screen": {
"resolution_x": 1920,
"resolution_y": 1080,
"color_depth": 24
}
}
}from flask import Flask, request, jsonify
from Extractor import process_request
app = Flask(__name__)
@app.route('/track', methods=['POST'])
def track_user():
"""Basic tracking endpoint"""
try:
# Extract PRIP data
user_data = process_request(request)
# Store in database (your implementation)
store_fingerprint_data(user_data)
return jsonify({
"status": "success",
"user_id": user_data.get("user_id_from_cookie"),
"visitor_id": user_data.get("visitor_id")
})
except ValueError as e:
return jsonify({"error": "Invalid data"}), 400
except Exception as e:
return jsonify({"error": "Server error"}), 500
def store_fingerprint_data(data):
"""Store fingerprint data in database"""
# Your database implementation here
passfrom flask import Flask, request, jsonify, session
from Extractor import process_request
import sqlite3
import datetime
app = Flask(__name__)
app.secret_key = 'your-secret-key'
class ResearchDB:
def __init__(self, db_path='research.db'):
self.db_path = db_path
self.init_database()
def init_database(self):
"""Initialize research database"""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS fingerprints (
id INTEGER PRIMARY KEY,
visitor_id TEXT,
user_id TEXT,
device_id TEXT,
timestamp TEXT,
fingerprint_data TEXT,
consent_given BOOLEAN,
study_id TEXT
)
''')
conn.commit()
conn.close()
def store_fingerprint(self, data, study_id, consent=False):
"""Store fingerprint with research metadata"""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''
INSERT INTO fingerprints
(visitor_id, user_id, device_id, timestamp, fingerprint_data, consent_given, study_id)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (
data.get('visitor_id'),
data.get('user_id_from_cookie'),
data.get('device_id_from_cookie'),
datetime.datetime.now().isoformat(),
json.dumps(data),
consent,
study_id
))
conn.commit()
conn.close()
research_db = ResearchDB()
@app.route('/research/collect', methods=['POST'])
def research_collect():
"""Research data collection with consent"""
try:
# Check consent
if not session.get('consent_given'):
return jsonify({"error": "Consent required"}), 403
# Extract data
user_data = process_request(request)
# Store with research metadata
study_id = session.get('study_id', 'default')
research_db.store_fingerprint(user_data, study_id, consent=True)
return jsonify({
"status": "success",
"message": "Data collected for research"
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/research/consent', methods=['POST'])
def give_consent():
"""Handle research consent"""
consent_data = request.json
if consent_data.get('agrees_to_research'):
session['consent_given'] = True
session['study_id'] = consent_data.get('study_id', 'default')
return jsonify({"status": "consent_granted"})
else:
return jsonify({"status": "consent_denied"})<!DOCTYPE html>
<html>
<head>
<title>Privacy Research Study</title>
</head>
<body>
<div id="consent-banner">
<h3>Research Participation</h3>
<p>This study collects browser fingerprinting data for privacy research.</p>
<button onclick="giveConsent()">I Agree to Participate</button>
<button onclick="declineConsent()">No Thanks</button>
</div>
<div id="research-content" style="display: none;">
<h1>Privacy Research Interface</h1>
<p>Thank you for participating in our research!</p>
</div>
<script src="P-RIP/PrivacyRipper.js"></script>
<script>
let prip;
async function giveConsent() {
// Send consent to server
const response = await fetch('/research/consent', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
agrees_to_research: true,
study_id: 'privacy_study_2025'
})
});
if (response.ok) {
// Initialize PRIP after consent
prip = new PrivacyRipper({
endpoint: '/research/collect',
debug: true
});
// Show research interface
document.getElementById('consent-banner').style.display = 'none';
document.getElementById('research-content').style.display = 'block';
// Start data collection
await collectResearchData();
}
}
function declineConsent() {
alert('Thank you for your consideration. No data will be collected.');
}
async function collectResearchData() {
try {
const fingerprint = await prip.collectFingerprint();
console.log('Research data collected:', fingerprint);
} catch (error) {
console.error('Research data collection failed:', error);
}
}
</script>
</body>
</html>def analyze_fingerprint_diversity(fingerprints):
"""Analyze uniqueness of collected fingerprints"""
unique_features = {}
for fp in fingerprints:
for feature, value in fp.items():
if feature not in unique_features:
unique_features[feature] = set()
unique_features[feature].add(str(value))
diversity_scores = {}
for feature, values in unique_features.items():
diversity_scores[feature] = len(values) / len(fingerprints)
return diversity_scores
def detect_browser_families(user_agents):
"""Categorize browsers from user agent strings"""
families = {
'Chrome': 0,
'Firefox': 0,
'Safari': 0,
'Edge': 0,
'Other': 0
}
for ua in user_agents:
if 'Chrome' in ua and 'Edge' not in ua:
families['Chrome'] += 1
elif 'Firefox' in ua:
families['Firefox'] += 1
elif 'Safari' in ua and 'Chrome' not in ua:
families['Safari'] += 1
elif 'Edge' in ua:
families['Edge'] += 1
else:
families['Other'] += 1
return familiesfrom flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["100 per hour"]
)
@app.route('/api/data', methods=['POST'])
@limiter.limit("10 per minute")
def limited_data_collection():
"""Rate-limited data collection endpoint"""
return process_request(request)from jsonschema import validate, ValidationError
FINGERPRINT_SCHEMA = {
"type": "object",
"properties": {
"visitor_id": {"type": "string", "maxLength": 100},
"user_agent": {"type": "string", "maxLength": 1000},
"screen_resolution": {
"type": "array",
"items": {"type": "integer"},
"minItems": 2,
"maxItems": 2
}
},
"required": ["visitor_id"]
}
def validate_fingerprint_data(data):
"""Validate incoming fingerprint data"""
try:
validate(data, FINGERPRINT_SCHEMA)
return True
except ValidationError as e:
print(f"Validation error: {e}")
return False| Code | Description | Solution |
|---|---|---|
| 400 | Invalid request data | Check data format and required fields |
| 403 | Missing consent | Implement proper consent mechanism |
| 429 | Rate limit exceeded | Reduce request frequency |
| 500 | Server processing error | Check logs and data format |
{
"error": "Invalid data format",
"code": 400,
"details": "Missing required field: visitor_id",
"timestamp": "2025-05-30T10:30:00Z"
}For more detailed examples and advanced usage patterns, see the examples directory in the repository.