Pick your browser below, run a short script on defly.io to export your statistics, then drag the downloaded file anywhere on this page.
Everything runs locally in your browser — nothing is uploaded.
(function () {
"use strict";
var TABLE_ID = "my-statistics-table";
var BUTTON_ID = "my-stats-button";
var POLL_MS = 400;
var STABLE_CHECKS = 4;
var TABLE_TIMEOUT_MS = 15000;
var DATA_TIMEOUT_MS = 45000;
var HARD_TIMEOUT_MS = 180000;
var DUR_RE = /\d+\s*h\s*\d+\s*m\s*\d+\s*s/i;
if (document.getElementById("defly-export-overlay")) {
console.warn("[defly-export] Already running.");
return;
}
var style = document.createElement("style");
style.id = "defly-export-style";
style.textContent =
"@keyframes deflySpin{to{transform:rotate(360deg)}}" +
"#defly-export-overlay button{font:inherit;cursor:pointer}";
document.documentElement.appendChild(style);
var overlay = document.createElement("div");
overlay.id = "defly-export-overlay";
overlay.style.cssText =
"position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;" +
"justify-content:center;background:rgba(15,17,21,.55);" +
"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;";
var box = document.createElement("div");
box.style.cssText =
"position:relative;display:flex;flex-direction:column;align-items:center;gap:14px;" +
"padding:30px 40px;border-radius:16px;background:#1F1F1E;color:#FAF9F5;" +
"box-shadow:0 12px 44px rgba(0,0,0,.5);min-width:240px;max-width:340px;text-align:center;";
var x = document.createElement("button");
x.textContent = "\u00D7";
x.title = "Cancel";
x.style.cssText =
"position:absolute;top:8px;right:10px;border:none;background:transparent;" +
"color:#8B887F;font-size:20px;line-height:1;padding:4px;";
x.onclick = cancel;
var spinner = document.createElement("div");
spinner.style.cssText =
"width:42px;height:42px;border-radius:50%;border:4px solid rgba(93,202,165,.25);" +
"border-top-color:#5DCAA5;animation:deflySpin .8s linear infinite;";
var label = document.createElement("div");
label.textContent = "Downloading stats\u2026";
label.style.cssText = "font-size:15px;font-weight:500;";
var sub = document.createElement("div");
sub.textContent = "Opening your statistics\u2026";
sub.style.cssText = "font-size:12px;color:#C0BEB4;line-height:1.45;";
var closeBtn = document.createElement("button");
closeBtn.textContent = "Close";
closeBtn.style.cssText =
"display:none;margin-top:4px;padding:8px 24px;border-radius:8px;border:1px solid #3C3A35;" +
"background:#2A2925;color:#FAF9F5;font-size:13px;";
closeBtn.onclick = remove;
box.appendChild(x);
box.appendChild(spinner);
box.appendChild(label);
box.appendChild(sub);
box.appendChild(closeBtn);
overlay.appendChild(box);
document.body.appendChild(overlay);
var timer = null;
function remove() {
if (timer) { clearInterval(timer); timer = null; }
if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
if (style.parentNode) style.parentNode.removeChild(style);
}
function cancel() { console.log("[defly-export] Cancelled."); remove(); }
function showStopped(title, msg, accent) {
if (timer) { clearInterval(timer); timer = null; }
spinner.style.display = "none";
x.style.display = "none";
label.textContent = title;
if (accent) label.style.color = accent;
sub.textContent = msg;
closeBtn.style.display = "inline-block";
}
function succeed(n) {
if (timer) { clearInterval(timer); timer = null; }
spinner.style.animation = "none";
spinner.style.border = "4px solid #5DCAA5";
x.style.display = "none";
label.textContent = "Done \u2014 saving file";
sub.textContent = n + " row" + (n === 1 ? "" : "s") + " saved to defly-stats.html";
setTimeout(remove, 1000);
}
function readyCount() {
var table = document.getElementById(TABLE_ID);
if (!table) return -1;
var rows = table.querySelectorAll("tbody tr");
if (!rows.length) rows = table.querySelectorAll("tr");
var n = 0;
for (var i = 0; i < rows.length; i++) {
var tds = rows[i].querySelectorAll("td");
if (tds.length >= 3 && DUR_RE.test(rows[i].textContent)) n++;
}
return n;
}
function download() {
var table = document.getElementById(TABLE_ID);
if (!table) return false;
try {
var html = table.outerHTML;
var blob = new Blob([html], { type: "text/html" });
var url = URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = url; a.download = "defly-stats.html";
document.body.appendChild(a); a.click(); a.remove();
setTimeout(function () { URL.revokeObjectURL(url); }, 1000);
return true;
} catch (e) { console.error("[defly-export] download error", e); return false; }
}
if (readyCount() <= 0) {
var btn = document.getElementById(BUTTON_ID);
if (btn) {
btn.click();
} else if (window.defly && typeof defly.showMyStats === "function") {
try { defly.showMyStats(); } catch (e) {}
} else {
showStopped("Not signed in",
"Couldn't find the My Statistics button. Open defly.io, sign in, then run this again.",
"#F0A594");
}
}
if (closeBtn.style.display !== "inline-block") {
var started = Date.now();
var lastCount = -2, stable = 0, everSawTable = false, everHadRows = false;
timer = setInterval(function () {
var elapsed = Date.now() - started;
var count = readyCount();
if (count >= 0) everSawTable = true;
if (count > 0) everHadRows = true;
if (!everSawTable && elapsed > TABLE_TIMEOUT_MS) {
showStopped("Not signed in",
"Your statistics panel didn't open. Sign in to your defly.io account, then run this again.",
"#F0A594");
return;
}
if (!everHadRows && elapsed > DATA_TIMEOUT_MS) {
showStopped("Not signed in",
"No statistics loaded. If you aren't signed in to a defly.io account, sign in and run this again.",
"#F0A594");
return;
}
if (elapsed > HARD_TIMEOUT_MS) {
if (everHadRows && download()) succeed(lastCount);
else showStopped("Timed out", "The stats took too long to load. Try running it again.", "#F0A594");
return;
}
if (count <= 0) {
sub.textContent = (count === -1) ? "Opening your statistics\u2026" : "Loading your stats\u2026";
lastCount = -2; stable = 0; return;
}
if (count === lastCount) stable++; else { stable = 0; lastCount = count; }
sub.textContent = count + " row" + (count === 1 ? "" : "s") + " loaded" +
(stable ? " \u2014 confirming\u2026" : "\u2026");
if (stable >= STABLE_CHECKS) {
if (download()) succeed(count);
else showStopped("Export failed", "Couldn't create the download. Try again.", "#F0A594");
}
}, POLL_MS);
}
console.log("[defly-export] Opening statistics and watching for data\u2026");
})();
Drop your defly-stats.html here, or pick it below. Loading more files adds their sessions (duplicates are ignored).
No data loaded yet
Drag the chart sideways, or scroll, to move along the timeline.