Skip to content

Instantly share code, notes, and snippets.

@xPaw
Created March 11, 2025 18:24
Show Gist options
  • Save xPaw/a00dd6d3bb1b53643996bf55647ce1ca to your computer and use it in GitHub Desktop.
Save xPaw/a00dd6d3bb1b53643996bf55647ce1ca to your computer and use it in GitHub Desktop.

Revisions

  1. xPaw created this gist Mar 11, 2025.
    61 changes: 61 additions & 0 deletions clock-sync-with-cloudflare-trace.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,61 @@

    function syncTime() {
    const startTime = performance.now();

    const xhr = new XMLHttpRequest();
    xhr.open("GET", "/cdn-cgi/trace", true);
    xhr.onreadystatechange = () => {
    if (xhr.readyState === 4) {
    const endTime = performance.now();
    const clientTimestamp = Date.now();

    // Get the date from the cloudflare response
    const match = xhr.responseText.match(/^ts=([0-9\.]+)/m);
    if (!match) {
    console.error("Unable to get remote time");
    return;
    }

    const serverTimestamp = Number.parseFloat(match[1]) * 1000;

    console.log("Client time:", clientTimestamp);
    console.log("Server time:", serverTimestamp);

    // Find the resource timing entry for our request
    const entry = performance
    .getEntriesByType("resource")
    .find((entry) => entry.name.endsWith("/cdn-cgi/trace") && entry.startTime >= startTime);

    // Calculate time offset
    if (entry) {
    // When we received the response headers is when the server timestamp was generated
    // So we need to adjust the current time by the amount of time that has passed since then
    const timeSinceResponse = endTime - entry.responseStart;

    // Client time when response headers were received
    const clientTimeAtResponse = clientTimestamp - timeSinceResponse;

    // Offset is difference between server time and client time at that moment
    g_TimeOffset = Math.floor(serverTimestamp - clientTimeAtResponse);

    console.log("Request time:", entry.responseStart - entry.requestStart);
    console.log("Time to response start:", entry.responseStart - entry.startTime);
    console.log("Time for response:", timeSinceResponse);
    } else {
    const roundTripTime = endTime - startTime;

    // Estimate that the server timestamp was captured halfway through the request
    // This is more accurate than assuming fixed travel times in both directions
    const estimatedCurrentServerTime = serverTimestamp + roundTripTime / 2;

    g_TimeOffset = Math.floor(estimatedCurrentServerTime - clientTimestamp);
    }

    console.log("Offset:", g_TimeOffset);
    console.log("Corrected time:", clientTimestamp + g_TimeOffset);
    console.log("Sanity check:", clientTimestamp + g_TimeOffset - serverTimestamp);
    }
    };

    xhr.send();
    }