speed test use html, js, cs, inline code

 


Here’s a single-file, copy-pasteable speed-test page using only HTML + inline CSS + vanilla JS. It measures latency (ping), download, and upload, shows your public IP, and works without any external libraries.

Tip: It tries Cloudflare’s public speed endpoint for download and httpbin for upload. If your hosting blocks cross-origin requests, set CUSTOM_DOWNLOAD_URL in the code to a file on your own server (e.g., a 50–200 MB file).

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Simple Speed Test</title>
<style>
  :root{
    --bg:#0b0f14; --panel:#111826; --muted:#8aa0b2; --text:#e8f1f8; --accent:#4cc9f0; --ok:#22c55e; --warn:#fbbf24; --err:#ef4444;
  }
  *{box-sizing:border-box}
  body{
    margin:0; font-family:system-ui,Segoe UI,Roboto,Inter,Arial,sans-serif;
    background: radial-gradient(1200px 800px at 80% -20%, #0f172a 0%, #0b0f14 40%, #070b10 100%);
    color:var(--text);
  }
  .wrapper{
    max-width:980px; margin:40px auto; padding:20px;
  }
  h1{margin:0 0 6px; font-size:28px; font-weight:800; letter-spacing:.2px}
  p.subtitle{margin:0 0 20px; color:var(--muted)}
  .grid{display:grid; gap:16px; grid-template-columns:repeat(12,1fr)}
  .card{
    grid-column: span 12;
    background:linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.02));
    border:1px solid rgba(255,255,255,.06);
    border-radius:18px; padding:18px;
    box-shadow: 0 10px 35px rgba(0,0,0,.35);
  }
  @media(min-width:760px){
    .span-4{grid-column: span 4;}
    .span-6{grid-column: span 6;}
    .span-8{grid-column: span 8;}
    .span-12{grid-column: span 12;}
  }
  .kpi{display:flex; align-items:baseline; gap:10px}
  .kpi .value{font-size:42px; font-weight:900}
  .kpi .unit{font-size:14px; color:var(--muted)}
  .row{display:flex; gap:10px; flex-wrap:wrap; align-items:center}
  button{
    background:var(--accent); color:#001018; border:0; padding:12px 18px;
    border-radius:12px; font-weight:800; cursor:pointer; transition:transform .08s ease;
  }
  button.secondary{background:transparent; color:var(--text); border:1px solid rgba(255,255,255,.18)}
  button:active{transform:translateY(1px)}
  .progress{
    width:100%; height:10px; border-radius:999px; background:#0d1420; overflow:hidden; border:1px solid rgba(255,255,255,.08)
  }
  .bar{height:100%; width:0%; background:linear-gradient(90deg, #4cc9f0, #22d3ee, #0ea5e9); transition:width .2s ease}
  .muted{color:var(--muted)}
  .status{font-size:14px}
  .badge{
    display:inline-flex; align-items:center; gap:8px; padding:8px 10px; border-radius:999px;
    background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.1); color:var(--muted)
  }
  code.inline{background:#0d1420; padding:2px 6px; border-radius:6px; border:1px solid rgba(255,255,255,.06)}
  .footer{margin-top:20px; font-size:12px; color:var(--muted)}
  .small{font-size:12px}
</style>
</head>
<body>
  <div class="wrapper">
    <h1>Speed Test</h1>
    <p class="subtitle">Lightweight HTML + JS speed test (no libs). Measures ping, download, and upload.</p>

    <div class="grid">
      <div class="card span-12">
        <div class="row" style="justify-content:space-between">
          <div class="row">
            <button id="btnStart">Start Test</button>
            <button id="btnStop" class="secondary">Stop</button>
          </div>
          <div id="badgeIP" class="badge">IP: <span id="ip">—</span></div>
        </div>
        <div class="row" style="margin-top:10px">
          <span class="badge">Server: <span id="server">Auto</span></span>
          <span class="badge">Location: <span id="loc">—</span></span>
        </div>
      </div>

      <div class="card span-4">
        <div class="kpi"><span class="value" id="latVal">—</span><span class="unit">ms</span></div>
        <div class="muted small">Latency (avg of 5 pings)</div>
      </div>

      <div class="card span-4">
        <div class="kpi"><span class="value" id="downVal">—</span><span class="unit">Mbps</span></div>
        <div class="progress" style="margin-top:10px"><div class="bar" id="downBar"></div></div>
        <div class="row" style="justify-content:space-between; margin-top:8px">
          <span class="muted small">Download</span>
          <span class="status small" id="downStatus">Idle</span>
        </div>
      </div>

      <div class="card span-4">
        <div class="kpi"><span class="value" id="upVal">—</span><span class="unit">Mbps</span></div>
        <div class="progress" style="margin-top:10px"><div class="bar" id="upBar"></div></div>
        <div class="row" style="justify-content:space-between; margin-top:8px">
          <span class="muted small">Upload</span>
          <span class="status small" id="upStatus">Idle</span>
        </div>
      </div>

      <div class="card span-12">
        <div class="row" style="justify-content:space-between; gap:8px">
          <div class="muted small">
            If remote servers block CORS, host a large file yourself and set
            <code class="inline">CUSTOM_DOWNLOAD_URL</code> below.
          </div>
          <div class="row">
            <button id="btnQuick5" class="secondary small">Quick Test</button>
            <button id="btnFull" class="secondary small">Full Test</button>
          </div>
        </div>
        <pre id="log" class="small" style="margin-top:10px; max-height:240px; overflow:auto; background:#0d1420; border:1px solid rgba(255,255,255,.06); border-radius:12px; padding:12px;"></pre>
      </div>
    </div>

    <div class="footer">
      Uses: Cloudflare <code class="inline">__down</code> for download, httpbin for upload, and <code class="inline">generate_204</code> for ping.
      Replace endpoints if needed. Results may be influenced by browser & Wi-Fi.
    </div>
  </div>

<script>
(() => {
  // ================== CONFIG ==================
  // If CORS blocks the download test, put your own large file URL here:
  const CUSTOM_DOWNLOAD_URL = ""; // e.g., "https://yourdomain.com/test/100mb.bin"

  // Default endpoints
  const PING_URL   = "https://www.google.com/generate_204";             // no-cors ok for timing
  const DOWN_URL   = CUSTOM_DOWNLOAD_URL || "https://speed.cloudflare.com/__down?bytes=25000000"; // ~25 MB
  const UP_POST    = "https://httpbin.org/post";                         // supports CORS
  const DOWN_TARGET_BYTES = 25_000_000; // only used for progress % if server doesn't expose length
  // ============================================

  const $ = sel => document.querySelector(sel);
  const fmt = (n, d=2) => Number.isFinite(n) ? n.toFixed(d) : "—";
  const log = (msg) => {
    const el = $("#log");
    const time = new Date().toLocaleTimeString();
    el.textContent += `[${time}] ${msg}\n`;
    el.scrollTop = el.scrollHeight;
  };

  // UI elements
  const latVal = $("#latVal");
  const downVal = $("#downVal");
  const upVal = $("#upVal");
  const downBar = $("#downBar");
  const upBar = $("#upBar");
  const downStatus = $("#downStatus");
  const upStatus = $("#upStatus");
  const serverSpan = $("#server");

  // State / cancellation
  let aborters = [];
  const makeAborter = () => {
    const c = new AbortController();
    aborters.push(c);
    return c;
  };
  const cancelAll = () => {
    aborters.forEach(a => a.abort());
    aborters = [];
    downStatus.textContent = "Canceled";
    upStatus.textContent = "Canceled";
  };

  // IP + location
  (async () => {
    try {
      const ipRes = await fetch("https://api.ipify.org?format=json", {cache:"no-store"});
      const {ip} = await ipRes.json();
      $("#ip").textContent = ip || "—";
    } catch {}
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        pos => {
          const {latitude, longitude} = pos.coords;
          $("#loc").textContent = `${latitude.toFixed(3)}, ${longitude.toFixed(3)}`;
        },
        () => { $("#loc").textContent = "Permission denied"; },
        {enableHighAccuracy:false, timeout:5000}
      );
    } else {
      $("#loc").textContent = "Unavailable";
    }
  })();

  // Latency test: do multiple pings and average
  async function testLatency(samples=5) {
    const times = [];
    for (let i=0;i<samples;i++){
      const s = performance.now();
      try {
        // Use no-cors so any 204/opaque is fine; we only care about timing
        await fetch(PING_URL, { mode:"no-cors", cache:"no-store", signal: makeAborter().signal });
        const e = performance.now();
        times.push(e - s);
        log(`Ping #${i+1}: ${fmt(e-s,1)} ms`);
        await new Promise(r => setTimeout(r, 150));
      } catch (err) {
        if (err.name === "AbortError") throw err;
        log(`Ping error: ${err.message || err}`);
      }
    }
    times.sort((a,b)=>a-b);
    const avg = times.reduce((a,b)=>a+b,0)/times.length || NaN;
    latVal.textContent = fmt(avg,1);
    return avg;
  }

  // Download test: stream a large response and measure throughput
  async function testDownload(secondsCap=12) {
    serverSpan.textContent = new URL(DOWN_URL).host;
    downStatus.textContent = "Starting…";
    downBar.style.width = "0%";

    const start = performance.now();
    let bytes = 0;
    let lastTick = start;
    let lastBytes = 0;

    try {
      const ctrl = makeAborter();
      const res = await fetch(DOWN_URL, { cache:"no-store", signal: ctrl.signal });
      const reader = res.body?.getReader?.();
      const contentLen = Number(res.headers.get("content-length")) || DOWN_TARGET_BYTES;

      if (!reader) {
        // fallback: try to read as blob (may pause UI, but works)
        const buf = await res.arrayBuffer();
        bytes = buf.byteLength;
      } else {
        downStatus.textContent = "Measuring…";
        while (true) {
          const {done, value} = await reader.read();
          if (done) break;
          bytes += value.byteLength;

          const now = performance.now();
          // Update progress bar
          const pct = Math.min(100, (bytes / contentLen) * 100);
          downBar.style.width = pct + "%";

          // Cap duration to avoid huge downloads
          if ((now - start) / 1000 > secondsCap) {
            ctrl.abort();
            break;
          }

          // Smooth live Mbps
          if (now - lastTick > 300) {
            const deltaBytes = bytes - lastBytes;
            const deltaSec = (now - lastTick)/1000;
            const mbpsLive = (deltaBytes * 8) / (1e6 * deltaSec);
            downVal.textContent = fmt(mbpsLive,1);
            lastTick = now; lastBytes = bytes;
          }
        }
      }

      const durSec = (performance.now() - start)/1000;
      const mbps = (bytes * 8) / (1e6 * durSec);
      downVal.textContent = fmt(mbps,2);
      downBar.style.width = "100%";
      downStatus.textContent = `Done • ${fmt(bytes/1e6,1)} MB in ${fmt(durSec,1)} s`;
      log(`Download: ${fmt(mbps,2)} Mbps (${fmt(bytes/1e6,1)} MB in ${fmt(durSec,1)} s)`);
      return mbps;
    } catch (err) {
      if (err.name === "AbortError") { log("Download aborted."); return NaN; }
      downStatus.textContent = "Failed";
      log(`Download error: ${err.message || err}`);
      return NaN;
    }
  }

  // Upload test: POST random blob to an echo endpoint and time it
  async function testUpload(sizeMB=10) {
    upStatus.textContent = "Preparing…";
    upBar.style.width = "0%";

    const sizeBytes = sizeMB * 1024 * 1024;
    // Create a deterministic blob without extra memory spikes by chunking
    const chunkSize = 1024 * 1024; // 1MB chunks
    const chunks = Math.ceil(sizeBytes / chunkSize);
    const parts = [];
    for (let i=0;i<chunks;i++){
      const len = Math.min(chunkSize, sizeBytes - i*chunkSize);
      parts.push(new Uint8Array(len)); // zeros are fine
      const pct = Math.round(((i+1)/chunks)*100);
      upBar.style.width = pct + "%";
      // Yield UI
      await new Promise(r => setTimeout(r, 0));
    }
    const blob = new Blob(parts, {type:"application/octet-stream"});

    try {
      upStatus.textContent = "Uploading…";
      const start = performance.now();
      const ctrl = makeAborter();
      const res = await fetch(UP_POST, {
        method:"POST",
        body: blob,
        signal: ctrl.signal,
      });
      const end = performance.now();
      const durSec = (end - start)/1000;
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const mbps = (sizeBytes * 8) / (1e6 * durSec);
      upVal.textContent = fmt(mbps,2);
      upBar.style.width = "100%";
      upStatus.textContent = `Done • ${sizeMB} MB in ${fmt(durSec,1)} s`;
      log(`Upload: ${fmt(mbps,2)} Mbps (${sizeMB} MB in ${fmt(durSec,1)} s)`);
      return mbps;
    } catch (err) {
      if (err.name === "AbortError") { log("Upload aborted."); return NaN; }
      upStatus.textContent = "Failed";
      log(`Upload error: ${err.message || err}`);
      return NaN;
    }
  }

  // Orchestrators
  async function quickTest(){
    disableButtons(true);
    log("=== Quick Test (Ping + 10s Download + 5MB Upload) ===");
    try {
      await testLatency(5);
      await testDownload(10);
      await testUpload(5);
    } catch (e) {
      if (e.name !== "AbortError") log("Quick test stopped.");
    } finally {
      disableButtons(false);
    }
  }

  async function fullTest(){
    disableButtons(true);
    log("=== Full Test (Ping + 12s Download + 10MB Upload) ===");
    try {
      await testLatency(7);
      await testDownload(12);
      await testUpload(10);
    } catch (e) {
      if (e.name !== "AbortError") log("Full test stopped.");
    } finally {
      disableButtons(false);
    }
  }

  function disableButtons(disabled){
    $("#btnStart").disabled = disabled;
    $("#btnQuick5").disabled = disabled;
    $("#btnFull").disabled = disabled;
    $("#btnStop").disabled = !disabled;
  }

  // Wire up buttons
  $("#btnStart").addEventListener("click", fullTest);
  $("#btnFull").addEventListener("click", fullTest);
  $("#btnQuick5").addEventListener("click", quickTest);
  $("#btnStop").addEventListener("click", () => {
    cancelAll();
    disableButtons(false);
  });

  // Initial server label
  serverSpan.textContent = (CUSTOM_DOWNLOAD_URL ? new URL(CUSTOM_DOWNLOAD_URL).host : new URL(DOWN_URL).host);
})();
</script>
</body>
</html>
 

 

 

Comments

Popular posts from this blog

Gmail Accounts

html css js calculator