3. JavaScript Get The Browser Unique Identifier Through The Browser Canvas Object

Huabin ZhangHuabin Zhang
5 min read

3.1 Basic principles

There are subtle differences in the "drawing" of the browser of each device, and these differences can be accurately recorded by canvas, which can be regarded as the digital fingerprint of the device.

These subtle differences include:

  • Operating system (Win/Mac), different operating systems render fonts differently

  • Browser kernel, the canvas API implementation details differ between browser kernels

  • Graphics card, GPU rendering, different graphics cards and GPU rendering will bring different antialiasing and shadow effects to the image

  • Installing Fonts, if the specified font is not installed on the system, the default font will be used

In response to these differences, although the text or image that the user sees "looks the same," the pixel content data is actually different.

3.2 Common usage scenarios

  • Mitigating Fraudulent Orders in E-Commerce Platforms

  • Techniques for Preventing Repetitive Voting in Online Polling Platforms

  • SaaS Login Security Protection

  • Ad Click Fraud Detection and Protection

  • User Data Insights & A/B Experiments

Code example

Example 1

In e-commerce systems, preventing fake orders (order fraud) typically involves combining multiple methods, such as detecting abnormal behavior through IP addresses, browser fingerprints, order frequency, etc.

// Obtain browser fingerprint
function getCanvasFingerprint() {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 200;
  canvas.height = 50;
  ctx.textBaseline = 'top';
  ctx.font = '16px Arial';
  ctx.fillStyle = '#f60';
  ctx.fillRect(0, 0, 200, 50);
  ctx.fillStyle = '#069';
  ctx.fillText('Check Fingerprint', 2, 2);
  ctx.strokeStyle = 'rgb(120, 186, 176)';
  ctx.strokeRect(1, 1, 198, 48);
  const dataURL = canvas.toDataURL();
  return dataURL;
}

// Obtain user IP address
async function getUserIP() {
  const response = await fetch('https://api.ipify.org?format=json');
  const data = await response.json();
  return data.ip;
}

// Combine fingerprinting and IP to prevent fake orders
async function handleOrder() {
  const fingerprint = getCanvasFingerprint();
  const ip = await getUserIP();

  // Simulate sending a request to the backend, where the backend will process the prevent fake orders logic.
  const orderData = {
    fingerprint: fingerprint,
    ip: ip,
    timestamp: Date.now(),
  };

  // Send order data to the backend for validation
  const response = await fetch('/api/checkOrder', {
    method: 'POST',
    body: JSON.stringify(orderData),
    headers: {
      'Content-Type': 'application/json',
    },
  });

  const result = await response.json();
  if (result.success) {
    console.log('Order successful!');
  } else {
    console.log('Duplicate order detected, submission is not allowed!');
  }
}

Example 2

In SaaS login security protection, the most common security measures include: prevention of brute force attacks, multi-factor authentication (MFA), login request restrictions, IP whitelisting / blacklisting, and more.

async function handleLogin(username, password) {
  const fingerprint = getCanvasFingerprint();  // Obtain browser fingerprint
  const ip = await getUserIP();  // Obtain user IP address

  // The login request sent to the backend includes the browser fingerprint and IP address.
  const loginData = {
    username: username,
    password: password,
    fingerprint: fingerprint,
    ip: ip,
    timestamp: Date.now(),
  };

  const response = await fetch('/api/login', {
    method: 'POST',
    body: JSON.stringify(loginData),
    headers: {
      'Content-Type': 'application/json',
    },
  });

  const result = await response.json();
  if (result.success) {
    console.log('登录成功');
  } else {
    console.log('登录失败: ' + result.message);
  }
}

Example 3

Using browser fingerprinting for data analysis and A/B testing can effectively help identify users and perform more precise experimental groupings.

A/B testing is typically used to compare the different impacts of two versions (A and B) on users, determining which version is more effective by controlling the assignment of experimental and control groups. Browser fingerprinting ensures that users are consistently assigned to the same group across multiple testing cycles.

function assignUserToABTest() {
  const fingerprint = getCanvasFingerprint();  // Obtain browser fingerprint
  const hash = hashFingerprint(fingerprint);  // Hash the fingerprint 
  const group = hash % 2 === 0 ? 'A' : 'B';  // Assign users to Group A or Group B based on the hash value
  return group;
}

function hashFingerprint(fingerprint) {
  // Use a simple hashing algorithm (which can be more complex depending on the requirements)
  let hash = 0;
  for (let i = 0; i < fingerprint.length; i++) {
    hash = (hash << 5) - hash + fingerprint.charCodeAt(i);
  }
  return hash;
}

// Suppose we have two versions of a button. Users will be assigned to Group A or Group B 
// based on their browser fingerprint and shown different button styles accordingly.
function renderABTestButton() {
  const userGroup = assignUserToABTest();  // Assign users to A/B groups

  const button = document.createElement('button');
  if (userGroup === 'A') {
    button.innerText = 'Button Version A';  // Button text for Group A
    button.style.backgroundColor = 'blue';
  } else {
    button.innerText = 'Button Version B';  // Button text for Group B
    button.style.backgroundColor = 'green';
  }

  button.addEventListener('click', () => {
    // Record click data, for example by sending it to the backend
    trackClick(userGroup);
  });

  document.body.appendChild(button);
}

function trackClick(group) {
  // Record click data
  console.log(`User clicked on ${group} button`);
  fetch('/api/trackClick', {
    method: 'POST',
    body: JSON.stringify({ group: group, timestamp: Date.now() }),
    headers: {
      'Content-Type': 'application/json',
    },
  });
}

renderABTestButton();  // Render the button

The main reasons for hashing browser fingerprints are to ensure consistency, reduce storage and computational complexity, and enhance privacy protection.

3.3 Advantages And Disadvantages

Advantages

No need for cookies, strong anonymity.

Disadvantages

There are privacy concerns, especially on a legal level, as user consent is required; otherwise, it may be illegal.

Additionally, some modern browsers have started to restrict this fingerprinting method.

Furthermore, it is not 100% unique and may be spoofed.

3.4 Best Practices Recommendations

  • Ensure legality and compliance by informing the user that such “data is being collected”

  • By combining browser fingerprinting, IP, user behavior and Captcha, make a comprehensive assessment of the user

  • Use mature libraries such as fingerprintjs, which provide more accurate data and include privacy protection options

0
Subscribe to my newsletter

Read articles from Huabin Zhang directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Huabin Zhang
Huabin Zhang