Network Speed Test Tool
Note: This tool simulates a speed test using browser requests to public APIs. It is an estimate and not a replacement for a dedicated speed test application.
Ping (Latency)
0
ms
Download
0
Mbps
Upload
0
Mbps
Live Log
Click "Start Test" to begin...
Test History
Your test history will appear here.
Your test history will appear here.
'; return; } ui.logList.innerHTML = testLog.map(log => `
${log.timestamp}
`).join('');
}
function logEntry(ping, download, upload) {
const timestamp = new Date().toLocaleString('en-US');
const logItem = {
timestamp,
ping: ping.toFixed(2),
download: download.toFixed(2),
upload: upload.toFixed(2)
};
testLog.unshift(logItem);
if (testLog.length > 50) testLog.pop(); // Limit log size
saveState();
renderLog();
}
function logToScreen(message, type = '') {
const line = document.createElement('p');
line.className = `nst-log-line ${type}`;
line.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
ui.liveLog.appendChild(line);
ui.liveLog.scrollTop = ui.liveLog.scrollHeight;
}
function showMessage(message, isError = true) {
ui.errorMsg.textContent = message;
ui.errorMsg.style.display = 'block';
}
// --- SPEED TEST LOGIC ---
async function testPing() {
logToScreen("Testing latency...");
const start = performance.now();
try {
await fetch('https://www.google.com', { mode: 'no-cors', method: 'HEAD', cache: 'no-store' });
const end = performance.now();
const ping = end - start;
logToScreen(`Ping test success: ${ping.toFixed(2)} ms`, 'success');
return ping;
} catch (e) {
logToScreen(`Ping test failed: ${e.message}`, 'error');
return -1;
}
}
async function testDownload() {
logToScreen("Testing download speed...");
const url = 'https://jsonplaceholder.typicode.com/photos'; // ~2.3MB JSON file, CORS enabled
try {
const start = performance.now();
const response = await fetch(url, { cache: 'no-store' });
const blob = await response.blob();
const end = performance.now();
const durationS = (end - start) / 1000;
const sizeBits = blob.size * 8;
const mbps = (sizeBits / durationS) / 1_000_000;
logToScreen(`Download test success: ${mbps.toFixed(2)} Mbps`, 'success');
return mbps;
} catch (e) {
logToScreen(`Download test failed: ${e.message}`, 'error');
return -1;
}
}
async function testUpload() {
logToScreen("Testing upload speed...");
const url = 'https://jsonplaceholder.typicode.com/posts'; // Accepts POST, CORS enabled
const sizeBytes = 5 * 1024 * 1024; // 5MB
const data = new Blob([new Uint8Array(sizeBytes)], { type: 'application/octet-stream' });
try {
const start = performance.now();
await fetch(url, { method: 'POST', body: data });
const end = performance.now();
const durationS = (end - start) / 1000;
const sizeBits = sizeBytes * 8;
const mbps = (sizeBits / durationS) / 1_000_000;
logToScreen(`Upload test success: ${mbps.toFixed(2)} Mbps`, 'success');
return mbps;
} catch (e) {
logToScreen(`Upload test failed: ${e.message}`, 'error');
return -1;
}
}
async function runTestSequence() {
if (isTesting) return;
isTesting = true;
ui.startBtn.disabled = true;
ui.startBtn.textContent = 'Testing...';
ui.loader.style.display = 'block';
ui.resultsContainer.style.display = 'block';
ui.errorMsg.style.display = 'none';
ui.liveLog.innerHTML = '';
// Reset results
ui.summaryPing.textContent = '...';
ui.summaryDownload.textContent = '...';
ui.summaryUpload.textContent = '...';
const ping = await testPing();
ui.summaryPing.textContent = ping < 0 ? 'N/A' : ping.toFixed(0);
const download = await testDownload();
ui.summaryDownload.textContent = download < 0 ? 'N/A' : download.toFixed(2);
const upload = await testUpload();
ui.summaryUpload.textContent = upload < 0 ? 'N/A' : upload.toFixed(2);
logToScreen("Test complete.");
currentTest = { ping, download, upload };
logEntry(ping, download, upload);
isTesting = false;
ui.startBtn.disabled = false;
ui.startBtn.textContent = 'Start Test';
ui.loader.style.display = 'none';
}
// --- PDF LOGIC ---
function downloadPDF(type) {
const { jsPDF } = window.jspdf;
if (!jsPDF || !window.jspdf.autoTable) { alert("PDF library not loaded!"); return; }
const doc = new jsPDF();
if (type === 'current') {
if (currentTest.ping === 0) {
alert("Please run a test before downloading.");
return;
}
doc.setFontSize(18);
doc.text("Network Speed Test Report", 14, 22);
doc.autoTable({
startY: 30,
theme: 'grid',
body: [
['Ping (Latency)', `${currentTest.ping.toFixed(2)} ms`],
['Download Speed', `${currentTest.download.toFixed(2)} Mbps`],
['Upload Speed', `${currentTest.upload.toFixed(2)} Mbps`],
]
});
doc.save("Speed_Test_Report.pdf");
} else if (type === 'log') {
if (testLog.length === 0) {
alert("Log is empty. Please run a test first.");
return;
}
doc.setFontSize(18);
doc.text("Network Speed Test Log", 14, 22);
doc.autoTable({
startY: 30,
head: [['Timestamp', 'Ping (ms)', 'Download (Mbps)', 'Upload (Mbps)']],
body: testLog.map(log => [log.timestamp, log.ping, log.download, log.upload]),
theme: 'striped',
headStyles: { fillColor: [22, 163, 74] } // var(--primary-color)
});
doc.save("Speed_Test_Log.pdf");
}
}
// --- EVENT LISTENERS ---
ui.startBtn.addEventListener('click', runTestSequence);
ui.downloadReportBtn.addEventListener('click', () => downloadPDF('current'));
ui.downloadLogBtn.addEventListener('click', () => downloadPDF('log'));
ui.clearLogBtn.addEventListener('click', () => {
testLog = [];
saveState();
renderLog();
});
// --- TABBING LOGIC ---
function switchTab(targetTabId) {
ui.tabContents.forEach(c => c.classList.remove('active'));
ui.tabButtons.forEach(b => b.classList.remove('active'));
document.getElementById(`nst-tab-${targetTabId}`).classList.add('active');
document.querySelector(`.nst-tab-button[data-tab="${targetTabId}"]`).classList.add('active');
}
function navigateTabs(dir) {
const tabs = Array.from(ui.tabButtons);
const active = tabs.find(t => t.classList.contains('active'));
let index = tabs.indexOf(active) + dir;
if (index < 0) index = 0; if (index >= tabs.length) index = tabs.length - 1;
switchTab(tabs[index].dataset.tab);
}
ui.tabButtons.forEach(button => button.addEventListener('click', () => switchTab(button.dataset.tab)));
ui.nextTabBtn.addEventListener('click', () => navigateTabs(1));
ui.prevTabBtn.addEventListener('click', () => navigateTabs(-1));
// --- UTILITY ---
function escapeHTML(str) { const p = document.createElement('p'); p.textContent = str; return p.innerHTML; }
// --- INITIALIZATION ---
loadState();
renderLog();
});
Ping: ${log.ping} ms, Download: ${log.download} Mbps, Upload: ${log.upload} Mbps
