Mastering Internet Speed Tests in Windows: CMD, PowerShell & a Dash of Nerdy Fun

You’re on your fourth coffee, your download speed feels like it’s coming through a dial-up modem, and your Zoom call looks like it’s been processed by Minecraft. You need to test your internet speed—but firing up a browser, dodging ads, and watching spinning gauges isn’t the vibe today.

Let’s do it like IT pros do—from the command line.

In this guide, you’ll learn how to use Speedtest CLI (the official command-line tool from Ookla) on Windows to test your internet connection like a tech-savvy ninja. We’ll start with simple usage, level up with automation in PowerShell, and hint at more powerful features hiding just beneath the surface.

Step 1: Download Speedtest CLI for Windows

Start by downloading the CLI tool from the official site:

👉 Download Speedtest CLI (Windows)

Unzip the contents, and inside you’ll find speedtest.exe. Put it somewhere practical like C:\Tools\Speedtest, or scatter it across your drive like digital confetti—your call.

(But seriously, add it to your system PATH for easier access from any directory.)

Step 2: Run Your First Speed Test

Open Command Prompt or PowerShell, and type:

PowerShell
C:\Tools\Speedtest\speedtest.exe

You’ll see:

  • Your ISP
  • Server location
  • Ping (latency)
  • Download speed
  • Upload speed
  • A shareable Result URL

It’s fast, clean, and totally browser-free. No ads, no popups, no mysterious “Install Our Extension!” buttons.

Want to Pick a Specific Server?

By default, Speedtest picks the nearest server automatically. But if you want to test a particular one (e.g., for consistency or curiosity), you can:

1. List Nearby Servers:

PowerShell
speedtest.exe --servers

2. Run the Test with a Specific Server ID:

PowerShell
speedtest.exe --server-id 12345

This is great when you’re trying to benchmark against a datacenter or a favorite ISP node.

Here’re the switches you can use with speedtest.exe

Switch Description
-h, --helpShow help information
-vIncrease verbosity (use multiple times like -vvv)
-V, --versionPrint version number
--accept-licenseAccept the license agreement (needed for automation)
--accept-gdprAccept GDPR agreement (required in the EU)
--servers, -LList nearby servers
--server-id=<id>, -sUse a specific server by ID
--host=<hostname>, -oUse server by hostname
--selection-detailsShow server selection information
--format=jsonOutput in compact JSON
--format=json-prettyOutput in pretty-printed JSON
--format=csv, tsv, jsonlOutput in various machine-readable formats
--output-headerInclude header row for CSV/TSV
--unit=MB/s, Mbps, MiB/s, etc.Customize output unit (for human-readable only)
--precision=<n>Set decimal precision (default: 2)
--interface=<name>, -IBind to a specific network interface
--ip=<address>, -iBind to a specific local IP address
--ca-certificate=<path>Use custom CA certificate (advanced use case)
--progress=yes|no, -pEnable/disable the progress bar
--progress-update-interval=<ms>Set interval (100–1000 ms) for progress updates

Basic PowerShell Automation

Let’s start automating with PowerShell, because typing the same command manually every hour is so last century.

Here’s a basic script to run a test and log it:

PowerShell
# Define full path to speedtest.exe (change this if needed)
$speedtestPath = "C:\Tools\Speedtest\speedtest.exe"

# Check if speedtest.exe exists
if (-Not (Test-Path $speedtestPath)) {
    Write-Error "speedtest.exe not found at $speedtestPath. Please verify the path."
    exit
}

# Run the speed test and parse JSON output
try {
    $output = & $speedtestPath --accept-license --accept-gdpr --format json | ConvertFrom-Json
}
catch {
    Write-Error "Failed to execute speedtest. Error: $_"
    exit
}

# Create a structured log object
$log = [PSCustomObject]@{
    Timestamp = Get-Date
    Ping      = $output.ping.latency
    Download  = [math]::Round($output.download.bandwidth / 125000, 2)  # Mbps
    Upload    = [math]::Round($output.upload.bandwidth / 125000, 2)    # Mbps
    Server    = $output.server.name
    ISP       = $output.isp
}

# Display results in console
Write-Host "`n=== Speedtest Results ===" -ForegroundColor Cyan
$log | Format-List

# OPTIONAL: Save results to CSV (uncomment the next line to enable logging)
# $log | Export-Csv -Path "C:\Tools\Speedtest\speedtest-log.csv" -Append -NoTypeInformation

💡 Pro Tip: The conversion bandwidth / 125000 gives you Mbps because 1 byte = 8 bits and 1 Mbps = 125,000 bytes per second.

Going Further: Extracting More Goodies

Let’s now use a slightly more advanced script based on one you may have seen online:

PowerShell
$speedtestcmd = & "C:\Tools\Speedtest\speedtest.exe" --accept-license -s 37149 -f json
$speedtestresult = $speedtestcmd | ConvertFrom-Json
$result = [PSCustomObject]@{
    Timestamp     = Get-Date
    ISP           = $speedtestresult.isp
    Server        = $speedtestresult.server.name
    Location      = "$($speedtestresult.server.location), $($speedtestresult.server.country)"
    PingLatencyMs = $speedtestresult.ping.latency
    JitterMs      = $speedtestresult.ping.jitter
    PacketLoss    = if ($speedtestresult.packetLoss) { "$($speedtestresult.packetLoss * 100)%" } else { "N/A" }
    DownloadMbps  = [math]::Round($speedtestresult.download.bandwidth / 1MB * 8, 2)
    UploadMbps    = [math]::Round($speedtestresult.upload.bandwidth / 1MB * 8, 2)
    ResultURL     = $speedtestresult.result.url
}
$result

Bonus: Set Alerts and Toast Notifications

Why stop there? Let’s have PowerShell complain when your speeds drop below expectations:

PowerShell
if ($result.DownloadMbps -lt 100) {
    Write-Warning "⚠️ Your download speed is under 100 Mbps!"
}

Or, if you’re feeling fancy, make Windows send you a toast notification:

PowerShell
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$toastXml = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
$toastXml.GetElementsByTagName("text")[0].AppendChild($toastXml.CreateTextNode("Speedtest Results"))
$toastXml.GetElementsByTagName("text")[1].AppendChild($toastXml.CreateTextNode("Download: $($result.DownloadMbps) Mbps, Upload: $($result.UploadMbps) Mbps"))
$toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml)
$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Speedtest CLI")
$notifier.Show($toast)

Boom. Speed alerts straight to your desktop like a proper sysadmin.

What Are Toast Notifications?

Toast notifications are the small pop-ups that appear in the bottom-right corner of your screen (like when Outlook says “You’ve got mail”). PowerShell can trigger these using Windows Runtime APIs — yes, you can be fancy now.

Full Script with Toast Notification & Comments

PowerShell
# ========================================
# Speedtest CLI with Toast Notification
# ========================================

# Path to speedtest.exe (adjust as needed)
$speedtestPath = "C:\Tools\Speedtest\speedtest.exe"

# Ensure speedtest.exe exists
if (-Not (Test-Path $speedtestPath)) {
    Write-Error "speedtest.exe not found at: $speedtestPath"
    exit
}

# Run speedtest with license/GDPR acceptance and JSON output
try {
    $output = & $speedtestPath --accept-license --accept-gdpr --format json | ConvertFrom-Json
}
catch {
    Write-Error "Error while running speedtest: $_"
    exit
}

# Extract and convert results into a friendly object
$result = [PSCustomObject]@{
    Timestamp     = Get-Date
    DownloadMbps  = [math]::Round($output.download.bandwidth / 125000, 2)
    UploadMbps    = [math]::Round($output.upload.bandwidth / 125000, 2)
    PingLatencyMs = $output.ping.latency
    ISP           = $output.isp
    Server        = $output.server.name
}

# Display results in console
Write-Host "`n=== Speedtest Results ===" -ForegroundColor Cyan
$result | Format-List

# ========================================
# Toast Notification Section
# ========================================

# Load Windows Runtime namespace for notifications
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null

# Use a two-line text template
$toastTemplate = [Windows.UI.Notifications.ToastTemplateType]::ToastText02
$toastXml = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent($toastTemplate)

# Set the notification's text content safely
$textNodes = $toastXml.GetElementsByTagName("text")
if ($textNodes.Count -ge 2) {
    $textNodes.Item(0).InnerText = "Speedtest Results"
    $textNodes.Item(1).InnerText = "Download: $($result.DownloadMbps) Mbps, Upload: $($result.UploadMbps) Mbps"
}
else {
    Write-Warning "Could not retrieve expected <text> elements from toast template."
    exit
}

# Create the toast notification object
$toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml)

# Show the notification using a named toast notifier
$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Speedtest CLI")
$notifier.Show($toast)

What This Script Does:

  1. Runs Speedtest CLI
    Executes a test and captures bandwidth, ping, ISP, etc.
  2. Displays the results in PowerShell
    Easy to check manually in the terminal
  3. Sends a toast notification
    With download & upload speed info, so you can see it even if the terminal is minimized

Optionally, you can schedule Regular Tests with Task Scheduler

  1. Open Task Scheduler
  2. Create a new task
  3. Set a trigger (e.g., every hour)
  4. Action: Start a program → powershell.exe
  5. Add argument: -ExecutionPolicy Bypass -File "C:\Scripts\SpeedTest.ps1"

Now your system checks itself before it wrecks itself—automatically.

Want to Go Even Deeper?

Inside the speedtest.zip package, there’s a lesser-known file: speedtest.md—a complete command-line reference that reveals even more options:

  • Use custom units (MB/s, GiB/s, kibps, etc.)
  • Output formats like csv, tsv, json-pretty, and jsonl
  • Adjust decimal precision with –precision
  • Bind tests to a specific network interface or IP
  • Control progress display and verbosity
  • Handle exit codes and errors with style

We’ll unpack that in Part 2: Speedtest CLI Deep Dive [I’m working on it now 🙂 ] —where things get really nerdy. You’ll learn how to integrate it with monitoring tools like Zabbix, parse CSVs, or even send results to a dashboard.

Summary

With speedtest.exe and a bit of PowerShell magic, you now have:

  • A lightweight, fast, ad-free way to test internet speed
  • Logging and historical monitoring
  • Custom scripts with alerts, notifications, and flexible output
  • A professional way to say, “It’s not me, it’s the ISP.”

And the best part? No browser tabs were harmed in the making of these tests.

Leave a Comment