A browser-based wizard that guides users through a network analysis for VoIP troubleshooting. It runs entirely in the browser — no installation, no backend, no data is sent anywhere. Use this as a Voys customer or feel free to make your own version.
This repository contains two distinct tools:
voip-diagnose*.html— Customer-facing diagnostic wizard (fills out a report step by step)report-analyzer.html— Support-staff tool for analyzing completed diagnosis reports
A single-page tool for Voys support staff. Paste one or more completed diagnosis reports into it to get an instant structured analysis with actionable tips.
- Multi-report support — Add multiple reports from the same customer to see trends over time
- Automatic diagnosis — Evaluates latency, jitter, packet loss, double-NAT, MOS, SIP connection, and audio devices; generates prioritized tips per finding
- Cross-report validation — Warns when reports appear to be from different customers (mismatched client ID or subnet)
- Trend charts — Line charts for latency, jitter, SIP response time, and average MOS across reports
- Per-call MOS bar chart — Shown as soon as two or more calls with MOS data are present (even with a single report)
- Audio device warnings — Detects Windows virtual routing devices ("Standaard", "Communicatie") and flags them as problematic
- Raw console log viewer — Displays the full webphone console log with:
- Calls highlighted in light blue
- Audio device change lines highlighted in amber
- Call-control HID blocks (headset button events) highlighted in lavender
- File prefixes (
index-PLAewdqz.js:60) stripped; timestamps shown in muted gray - Fullscreen expand button for easier reading
- Portal link — Direct link to the customer in the Voys partner portal (when a client ID is present in the log)
The analyzer parses both structured report output (from the diagnostic wizard) and raw webphone console logs pasted directly from browser DevTools.
For console logs, calls are detected from session events (session is accepted, call was terminated, MOS stats for terminated). Both timestamp formats are supported:
| Format | Example |
|---|---|
| Dutch / Windows Chrome | [23-4-2026, 15:23:50] |
| US / Mac Chrome | [4/23/2026, 1:14:52 PM] |
Reports in Dutch and English are both supported.
| File | Language | Audience | Notes |
|---|---|---|---|
voip-diagnose.html |
Dutch | Voys Netherlands customers | — |
voip-diagnose-eng.html |
English | International customers and support | — |
voip-diagnose-sa.html |
English | Voys South Africa customers | SA-specific endpoints |
diagnose-nor.html |
Dutch | Voys Netherlands — no report variant | Skips step 4; manual checks note shown as result card |
voip-diagnose-ger.html |
German | Voys Germany customers | DE-specific endpoints |
voip-diagnose-be.html |
Dutch | Voys Belgium customers | BE-specific endpoints |
Each file is a single self-contained HTML file that can be opened directly in a browser or hosted on any static web server.
South Africa (voip-diagnose-sa.html) uses SA-specific endpoints instead of the Netherlands equivalents:
| Original | South Africa |
|---|---|
ha.voys.nl |
sip.voys.co.za |
www.osso.nl |
clientzone.afrihost.com |
websocket.voipgrid.nl |
websocket.voys.co.za |
Germany (voip-diagnose-ger.html) uses DE-specific endpoints instead of the Netherlands equivalents:
| Original | Germany |
|---|---|
ha.voys.nl |
ha.voys.de |
www.osso.nl |
www.vodafone.de |
websocket.voipgrid.nl |
websocket.voipgrid.nl (same) |
Belgium (voip-diagnose-be.html) uses BE-specific endpoints instead of the Netherlands equivalents:
| Original | Belgium |
|---|---|
ha.voys.nl |
ha.voys.be |
www.osso.nl |
www.proximus.be |
websocket.voipgrid.nl |
websocket.voipgrid.nl (same) |
No report (diagnose-nor.html) is a Dutch variant that skips step 4. The note about incomplete manual checks is displayed as an orange result card instead of a subtle text line.
The tool walks through four steps:
- Device type — Webphone (browser/app) or desk phone/DECT handset
- Device details — Brand, model, IP address (desk phones only)
- Network analysis — Automatic and optional manual tests, including a SIP connectivity test over WebSocket
- Report — A plain-text summary ready to paste into a support ticket
For webphone users, an optional console log can be added to the report. The tool automatically parses it for individual calls and displays a summary table with call direction, duration, and MOS score per call.
The tool runs as a single HTML file. This means it can be shared as an email attachment, hosted on GitHub Pages, or opened from a USB stick. A support agent can send one link; the customer opens it in any browser. No setup required.
The tool automatically measures HTTP response times to three servers: Voys, OSSO, and Cloudflare. This gives an instant baseline without any user action.
Important limitation: browser-based measurements are HTTP response times, not ICMP ping. They include TCP connection overhead, TLS handshake time, and server processing. Results are typically 2–5× higher than a real ping. Use these values for comparison between servers, not as absolute latency figures.
Three servers are used so that one slow result can be put in context. If all three are slow, the connection itself is the bottleneck. If only one is slow, that server may be geographically distant.
The optional terminal ping (ping ha.voys.nl -n 20 on Windows, ping -c 20 ha.voys.nl on Mac/Linux) uses ICMP, which measures raw round-trip time without HTTP overhead. This is how VoIP latency is typically assessed.
The tool parses the pasted output automatically. It extracts min/avg/max, packet loss, and jitter from Windows, macOS, and Linux formats.
When terminal ping is available, it takes priority over the browser measurement in both the diagnosis and the report.
Jitter is the variation in round-trip time between consecutive packets. A connection with 40 ms average latency but 2 ms jitter sounds fine. A connection with 20 ms average latency but 60 ms jitter causes audible glitches and robotic-sounding audio.
The tool calculates jitter as the standard deviation of individual ping reply times. Terminal ping results are used when available; browser ping jitter is used as a fallback.
Method 1 — Automatic (WebRTC/STUN): The tool uses a WebRTC peer connection to a STUN server. If the external IP address returned by STUN is a private IP (e.g. 10.x.x.x or 192.168.x.x), the connection is behind CGNAT — two layers of NAT performed by the ISP. This is detected automatically on page load.
Method 2 — Traceroute (more accurate): CGNAT detection only catches the ISP layer. A customer with two routers at home (e.g. an ISP modem/router plus their own router) will not be caught by method 1. The optional traceroute paste lets the tool inspect the actual network path. If two different private subnets appear in the first hops, double-NAT is detected.
The traceroute result takes priority over the WebRTC result when both are available.
Why not Google STUN? stun.l.google.com is the most common STUN server used in examples. For a Voys-branded tool, using a Google endpoint raises privacy concerns (Google logs STUN requests). The tool uses stun.cloudflare.com:3478 instead, which has a clear privacy policy and no data retention for STUN traffic.
The tool opens a WebSocket connection to wss://websocket.voipgrid.nl (or the SA equivalent) and sends a SIP OPTIONS request. This measures two values separately:
- Connection time — TCP + TLS + WebSocket handshake (how long before any data can be sent)
- Response time (RTT) — round-trip of the SIP OPTIONS request once the connection is open
A failed test (timeout, error, or connection closed before response) suggests a firewall is blocking WSS connections.
What the SIP test cannot detect — SIP ALG
SIP ALG is a router feature that inspects and rewrites unencrypted SIP traffic on UDP port 5060. Because this test uses WSS (TLS-encrypted WebSocket), the router cannot inspect it. The SIP test will pass even when SIP ALG is active.
For this reason, the tool shows a SIP ALG note in the diagnosis when the device type is a desk phone or DECT and all other tests pass: desk phones use UDP SIP and are affected by SIP ALG, while webphones use WSS and are not.
Modern browsers (Chrome 75+, Firefox) apply mDNS obfuscation: instead of exposing a real local IP address like 192.168.1.45, they return a hostname like abc123.local. This is a deliberate privacy protection.
Because of this, the tool always shows a manual IP input field. If WebRTC does succeed in returning a real IPv4 address, it is pre-filled automatically — but the field stays visible so the user can correct it.
For a desk phone or DECT handset, the tool checks whether the phone and the computer are on the same network (same /24 subnet prefix). If they are on different subnets, the phone may not be able to reach the Voys platform.
This check is not applicable for webphones, since a webphone runs on the same machine as the browser by definition.
| Value | Assessment | What it means |
|---|---|---|
| < 50 ms | Good | Excellent for VoIP — no audible delay expected |
| 50–100 ms | Moderate | Acceptable, but noticeable on long-distance calls |
| > 100 ms | High | Likely causing delays or echo in conversations |
Note: browser ping values are roughly 2–5× higher than ICMP ping. Use terminal ping for reliable latency figures.
| Value | Assessment | What it means |
|---|---|---|
| < 20 ms | Good | Stable connection — audio should be clear |
| 20–50 ms | Moderate | Slight fluctuation — possible minor glitches |
| > 50 ms | High | Unstable connection — audible dropouts likely |
High jitter is often caused by wifi interference, a congested network, or a failing cable. Switching from wifi to a wired connection usually resolves it.
| Value | Assessment |
|---|---|
| 0% | Normal |
| 1–2% | Minor — may cause occasional audio glitches |
| > 2% | Significant — causes poor or unusable call quality |
Packet loss is only measured via the terminal ping (the browser measurement cannot detect it).
Double-NAT means network traffic passes through two separate NAT routers before reaching the internet. This can prevent VoIP registration, cause one-way audio, or drop calls entirely.
Common causes:
- ISP modem/router in routing mode + customer's own router (fix: set ISP device to bridge mode)
- CGNAT at the ISP level (fix: ask ISP for a public IP address, sometimes as a paid option)
If the computer IP and device IP start with different numbers, they are on different network segments. The phone can typically still reach the internet, but it may not be able to communicate with the computer or register with Voys correctly.
Example:
- Computer:
192.168.1.45— Device:192.168.1.100→ Same subnet ✓ - Computer:
192.168.1.45— Device:10.0.0.100→ Different subnet ⚠
The tool includes step-by-step instructions for finding the IP address on:
- Yealink (desk phone and DECT base station)
- Gigaset (DECT)
- Snom (desk phone)
- Grandstream (desk phone)
- Cisco SPA (desk phone)
- Fanvil (desk phone)
- Other (manual IP entry, no step-by-step guide)
The terminal ping parser handles:
| Format | Example summary line |
|---|---|
| Windows (English) | Minimum = 12ms, Maximum = 25ms, Average = 18ms |
| Windows (Dutch) | Minimum = 12ms, Maximum = 25ms, Gemiddeld = 18ms |
| macOS | round-trip min/avg/max/stddev = 10.5/18.2/25.1/4.3 ms |
| Linux | rtt min/avg/max/mdev = 10.5/18.2/25.1/4.3 ms |
| IPv6 fallback | Parses individual time=Xms lines when no summary is present |
When a webphone console log is pasted into the report step, the tool automatically extracts all calls from it.
What is parsed:
| Field | Source in log |
|---|---|
| Date and time | Timestamp at the start of each log line |
| Direction | outgoing / incoming in the session event |
| Duration | Time between session is accepted and call was terminated |
| MOS score | MOS stats for terminated <sessionId> line |
| Phone number | number / phoneNumber / remoteNumber field, if present |
MOS thresholds:
| Score | Assessment |
|---|---|
| ≥ 4.0 | Good |
| 3.6–4.0 | Moderate |
| < 3.6 | Poor |
The parsed calls appear as a table directly below the paste area, and as a structured CALLS section in the copyable report text. The overall average MOS across all calls is shown in both places.
The log lines do not need to be clean — the parser handles the filename.js:linenum prefix that browsers add when copying from the DevTools console.
- No data is sent to any server
- The STUN request to
stun.cloudflare.com:3478is used only to detect the external IP address; no call data is involved - Cloudflare does not retain STUN traffic logs
- Everything else runs locally in the browser