The URDS Log Validator is a browser-based tool for FM DXers. It reads CSV log files that were recorded by TEF6686 / TEF6687-based receivers (URDS format), validates each entry against the live fmdx.org transmitter database, and assigns a confidence score to every reception.
The tool helps you to:
9730 = 97.3 MHz97.3 = 97.3 MHzThe header bar runs across the full width of the page and consists of three zones:
| Zone | Contents |
|---|---|
| Left | Application title URDS Log Validator |
| Centre | Toast notification area, loading progress bar with percentage label, and the cancel validation button (✕) |
| Right | 📖 Manual link – opens this documentation in a new tab. The button is positioned at the far right of the header bar. |
https://highpoint.fmdx.org/manuals/urds-log-validator-Documentation.html.
Directly below the header bar is the upload / action bar. Its buttons change visibility depending on the application state:
| Button | Always visible? | Purpose |
|---|---|---|
| Upload File | Yes | Opens the OS file picker to select a .csv file |
| Process from Clipboard | Yes | Reads URDS log text directly from the clipboard |
| Show Filters / Hide Filters | Yes | Toggles the filter bar visibility |
| No import duplicates (checkbox) | Yes | Discards duplicate Freq+PI+PS combinations on import |
| ⚡ Auto-Fix All | After validation | Runs the automatic fix algorithm on all incomplete rows |
| ⬇ Download filtered CSV | After validation | Exports currently visible rows as an enriched CSV file |
| 📋 Copy to Clipboard | After validation | Copies currently visible rows as CSV text to the clipboard |
Click the Upload File button in the upload bar. A file picker opens. Select your .csv log file. The tool accepts only .csv files. If you select a file with a different extension a warning toast appears and the upload is blocked.
validated_originalname.csv or bandscan_originalname.csv).
If your log is already in the clipboard (copied from a text editor or directly from the receiver software), click Process from Clipboard. The tool reads the clipboard text and processes it exactly like a file upload. An empty clipboard triggers an orange warning toast.
The checkbox No import duplicates (next to the upload buttons) controls what happens when the CSV contains multiple rows with identical Frequency + PI + PS combinations:
| State | Behaviour |
|---|---|
| ☐ Unchecked (default) | All rows are imported, including duplicates. Useful for time-series analysis or finding the best-quality reception of each station. |
| ☑ Checked | Only the first occurrence of each Freq + PI + PS combination is imported. Speeds up processing of long overnight logs significantly. |
Immediately after the CSV is loaded, the tool determines the receiver location from the GPS coordinates stored in the first valid log row. It then downloads the complete FM transmitter database for that location from:
https://cors-proxy.de:13128/https://maps.fmdx.org/api/?qth={lat},{lon}
The download is cached in the browser's localStorage for the current calendar day. On the next load the cached data is used – no second network request is made unless you clear your browser storage or use a different location.
urds_qth_51.3_12.4_2026-3-22. Old entries from previous days are automatically removed when a new entry is written for the same location.
After the station database is loaded, all rows are validated asynchronously. This keeps the browser responsive even for very large log files (thousands of rows). The progress is shown in the header bar centre zone:
| Element | Description |
|---|---|
| Toast message | Shows the current status text, e.g. "Validating… 412 / 2267" or "Station database loaded from cache." |
| Progress bar | HTML <progress> element showing percentage completion. Disappears automatically 800 ms after reaching 100%. |
| ✕ Cancel button | A small red circular button that appears only during validation. Clicking it stops the validation loop immediately. Rows that have already been validated remain usable; unvalidated rows show a "?" score circle. |
The table updates live every 500 ms during validation – you can already sort, filter, and interact with already-validated rows before the full validation completes.
| Column | Source | Description |
|---|---|---|
| # | Row index | Sequential number (1-based). Click the ▶ button to expand the detail row. The number reflects the original import order regardless of sorting. |
| Date | CSV field 12 (timestamp) | UTC date of the reception (YYYY-MM-DD). |
| Time | CSV field 12 (timestamp) | UTC time of the reception (HH:MM:SS), milliseconds stripped. |
| MHz | CSV field 3 (frequency in Hz) | Tuned frequency in MHz, displayed with 2 decimal places (e.g. 97.30). |
| PI | CSV field 13 | Programme Identification code (hex, e.g. F201). Red + DB suggestion shown when the received PI does not match the database entry. Underlined when corrected by Fix. |
| PS | CSV field 15 | Programme Service Name (8 characters). Spaces shown as underscores (_). Red + DB variants shown when the received PS does not match. Underlined when corrected. Original casing is preserved throughout. |
| Station | fmdx.org / pre-filled / Fix | Human-readable station name from the database (e.g. "France Inter"). |
| ID | CSV field 30 / Fix | FMLIST station ID. Shows "No ID" in red italic when empty or zero. A 🌐 map icon appears when a database match exists (opens the embedded Leaflet map overlay for this row). A ⚠ warning icon appears when multiple DB entries on the same frequency share the same PI and PS. |
| TX / City | fmdx.org / pre-filled / Fix | Transmitter city and ITU country code, e.g. "Strasbourg (F)". |
| ERP | fmdx.org / pre-filled / Fix | Effective Radiated Power in kW. |
| Pol | fmdx.org / pre-filled / Fix | Antenna polarisation: H (horizontal), V (vertical), or M (mixed). |
| km | Calculated | Great-circle distance from receiver to transmitter in km (whole number). Calculated from DB coordinates or pre-filled TX coordinates. |
| Az° | Calculated | Azimuth from receiver to transmitter in degrees (whole number, 0–360). |
| dBµV | CSV field 5 | Signal level in dBµV (one decimal place). |
| ITU / Flag | fmdx.org / pre-filled / Fix | Country flag image (from flagcdn.com) and ITU country code. Falls back to a custom image for ITU codes without an ISO country code. |
| AF-Check | Calculated | Alternate Frequency validation result: how many of the broadcast AF frequencies could be confirmed in the database with the same PI. Shown as 2/4 (50%) with colour coding (green / orange / red). |
| Score | Calculated | Confidence score 0–100. See Section 7 for the calculation. Fixed rows always show 100 in blue. |
| Actions | — | Three buttons: ✏ Fix (manual fix dialog), ⚡ Auto (automatic single-row fix), 🗑 Del (delete this or all matching rows). |
0 or 0.0 (Gulf of Guinea artefact) are silently discarded.
Each log row is validated against the fmdx.org database. The result is a score between 0 and 100 that reflects how confidently the received station has been identified.
| Component | Points | Condition |
|---|---|---|
| PI match | 40 | Received PI code found in the database on this exact frequency |
| PS match | 30 | Received PS name matches one of the known PS variants in the database (case-insensitive comparison, original casing preserved for display) |
| AF validation | up to 20 | Percentage of alternate frequencies that could be confirmed × 0.20 (e.g. 3/4 AF confirmed = 75% × 0.20 = 15 points) |
| No AF data | up to 10 | Bonus +5 for PI match and +5 for PS match when no AF list is present in the log row (substitutes the missing AF component) |
| Uniqueness | 10 | Only one DB entry matches on this frequency → single confident identification with no ambiguity |
| Level | Meaning | Typical score range |
|---|---|---|
| Level 1 | Freq + PI + PS all match | 75–100 |
| Level 2 | Freq + PI match, PS not in DB variants | 40–75 |
| Level 3 | Freq + PS match only, PI mismatch | 30–55 |
| No match | Neither PI nor PS found on this frequency | 0 |
Each row in the table is colour-coded. Fixed rows always appear in blue regardless of score:
| Colour | Score range | Meaning |
|---|---|---|
| Green | ≥ 75 | Good match – PI, PS and usually AF confirmed. High confidence identification. |
| Yellow | 40 – 74 | Uncertain – PI confirmed but PS or AF partially unmatched. Manual review recommended. |
| Red | 0 – 39 | Poor / mismatch – significant discrepancy between received data and database. |
| White/grey | — | Unidentified – no matching entry found in the database for this frequency / PI / PS combination. |
| Blue | 100 (fixed) | Manually or automatically fixed entry. All fields have been set from the database. |
The score circle in the Score column mirrors the row colour:
85 ≥75% (green) 55 40–74% (orange) 12 <40% (red) 100 Fixed (blue)
The summary bar appears directly below the upload buttons as soon as a log is loaded. It shows at a glance how many entries are in the log and how they are distributed across score categories.
| Element | Description |
|---|---|
| Total | Total number of rows imported from the CSV (after "No import duplicates" filtering if active). |
| Identified | Rows that have at least one matching database entry (bestMatch found) or non-empty pre-filled station data. |
| Showing | Number of rows currently visible after all active filters are applied. |
| Ring ≥75% | Mini ring gauge (36×36 px canvas): number of non-fixed rows with score ≥ 75. The ring fill proportion represents the share of all rows. The number is drawn centred inside the ring. |
| Ring 40–74% | Mini ring gauge for medium-confidence rows (orange). |
| Ring <40% | Mini ring gauge for low-confidence and unmatched rows (red). |
| Ring Fixed | Mini ring gauge for rows that have been fixed manually or automatically (blue). |
| Avg gauge | Larger ring (44×44 px) showing the average score across all validated rows. Fixed rows count as 100. The label text colour follows the same green/orange/red thresholds. |
| Legend | Quick colour reference strip for row background colours (Good match / Uncertain / Poor / Unidentified / Fixed). |
Click the Show Filters button (toggles to Hide Filters) to reveal the filter bar. The filter bar is organised in two rows. All filters are applied simultaneously and update the table in real time.
The dropdown Score / colour limits the table to rows in a specific confidence category:
| Option | Shows rows where… |
|---|---|
| All entries | No score filter – all rows visible |
| 100% (perfect) | Score = 100 exactly |
| ≥ 75% 🟢 | Score ≥ 75 (green rows) |
| 40–74% 🟡 | Score 40–74 (yellow rows) |
| < 40% 🔴 | Score below 40 (red rows) |
| Unidentified only ⬜ | No database match found at all |
| Manually fixed 🔵 | Fixed = true (blue rows) |
The five coloured filter pills (🟢 ≥75%, 🟡 40–74%, 🔴 <40%, 🔵 Fixed, ⬜ Unidentified) act as toggle buttons for the same filter. Clicking an active pill deactivates the filter (returns to "All entries"). The pills are located in filter row 1, directly after the Reset Filters button.
The distance filter (filter row 2) shows only rows where the calculated distance from the receiver to the transmitter is at least the selected value:
| Checkbox | Minimum distance | Typical use |
|---|---|---|
| ≥ 150 km | 150 km | Suppress immediate local stations |
| ≥ 300 km | 300 km | Domestic skip-zone DX |
| ≥ 700 km | 700 km | Tropospheric duct DX |
| ≥ 1300 km | 1300 km | Sporadic-E DX |
| Custom + input | Any value in km | Fine-grained distance threshold |
Only one distance preset can be active at a time. Selecting a different preset automatically deselects the previous one. The custom numeric input field activates when the Custom checkbox is ticked.
The Exclude PI codes input field (filter row 2) accepts a comma-separated list of PI codes to hide from the table, e.g. F201,F731. This is useful to temporarily suppress known local stations. The filter is case-insensitive and the leading 0x prefix is stripped automatically.
The search box (🔍 Search table…) in filter row 2 filters the table by any text. The following fields are searched simultaneously: Date, Time, Frequency, PI, PS, Station, City, ITU, Station ID.
| Checkbox | Location | Effect |
|---|---|---|
| Hide unidentified | Filter row 1 | Removes rows with no database match from the visible table (does not delete them from memory). |
| Hide duplicates | Filter row 1 | Within the currently sorted order, shows only the first occurrence of each unique Freq + PI + PS combination. All subsequent duplicates are hidden. This is a display filter only – all rows remain in memory and are exported when the filter is cleared. |
The Reset Filters button (filter row 1) clears all filters, checkboxes, text inputs, and distance presets in one click.
Click any column header to sort the table by that column. A second click on the same header reverses the sort direction. The current sort column is indicated by a ▲ (ascending) or ▼ (descending) arrow next to the header text.
| Column | Sort type | Notes |
|---|---|---|
| #, MHz, ERP, km, Az°, dBµV, Score | Numeric | Ascending by default (smallest first) |
| Date, Time, PI, PS, Station, TX/City, ITU, Pol | Alphabetical | A→Z ascending by default |
| ID | Alphabetical | Empty IDs sort first |
| AF-Check | Numeric | Sorted by AF score percentage (0–100) |
Click the ▶ button at the start of any row to expand its detail view. The button changes to ▼ when open. Click again to collapse.
The detail row shows a full breakdown of how the validation score was computed:
| Badge | Colour | Meaning |
|---|---|---|
| PI | Green / Red | Whether the received PI was found in the database on this frequency |
| PS | Green / Orange | Whether the received PS matches any known DB variant (case-insensitive) |
| Unique | Green | Exactly one database entry matched → high-confidence identification |
| Multi | Orange | Multiple candidates matched → ambiguous identification, review recommended |
| Level | Grey (info) | Match level: Freq+PI+PS (best) / Freq+PI only / Freq+PS only |
| AF | Green / Orange / Red | AF validation results: ✓ = confirmed in DB with same PI, ✗ = not found. "No AF data in log entry" shown when the AF field is empty. |
At the bottom of the detail row, a collapsible "All DB entries on X MHz" table shows every station the database knows for this frequency – useful for manual cross-checking in ambiguous cases. This section only appears when there are two or more DB entries on the frequency.
When the validation reveals that metadata is missing or incorrect, the fix functions let you update the row with correct data directly from the database.
The ✏ Fix button opens the Fix overlay for that row. The overlay has three sections:
A checkbox "Show only transmitters with matching PI + PS" pre-filters the candidate list to entries that match both PI and PS. Uncheck it to see all transmitters on this frequency. The transmitter list is sorted by ascending distance from the receiver (nearest first). Each entry shows station name, city, PI, PS, ERP, ITU code, and calculated distance in km.
After selecting a transmitter, the second dropdown shows all known PS name variants for that transmitter. The default option "Keep logged PS: …" preserves the received PS with its original casing as-is. Select a DB variant to replace it in the exported CSV. Original casing from the database is preserved throughout.
A comparison table shows the current values (left column) and the new values from the selected candidate (right column). Changed values are shown underlined and bold in blue. Hover over an underlined value to see the old value in a tooltip ("Was: …").
| Button | Effect |
|---|---|
| Apply to this entry only | Updates only the current row. The row is marked as fixed (blue background, score forced to 100). |
| Apply to all matching entries | Updates every row in the entire log that has the same frequency and PI code with the selected candidate. This is the fastest way to fix a station that was logged many times during a session. |
| Cancel | Closes the overlay without making any changes. |
The ⚡ Auto button applies an automatic best-candidate fix to a single row without opening the overlay. The algorithm picks the best candidate using this priority ladder:
If no candidate can be found at all, a red toast notification "Row N: no DB candidate found." is shown and no changes are made.
The ⚡ Auto-Fix All button (in the upload bar, visible after loading) runs the automatic fix algorithm on every row that is not yet complete. An animated progress overlay shows the current progress:
fixed = true AND a valid station ID is already present are skipped.
The 🗑 Del button opens the Delete confirmation overlay. It always shows a preview table of the row(s) that would be affected. The overlay can also be dismissed by clicking outside the modal box.
| Button | Effect |
|---|---|
| Delete this entry only | Removes only the single row that was clicked. |
| Delete all matching (N entries) | Removes all rows sharing the same Freq + PI + PS combination. The count N is shown in the button label. This button is hidden when only one row matches. |
| Cancel | Closes the overlay without deleting anything. Clicking outside the modal also cancels. |
The 🌐 globe icon appears in the ID column for any row that has a database match (a best-match entry with known coordinates). Clicking it opens a full-screen embedded map overlay powered by Leaflet.js and OpenStreetMap tiles. Leaflet is loaded lazily – no map libraries are downloaded until the globe icon is first clicked.
Click the 🌐 globe icon in the ID column of any row. The map overlay appears, covering the full viewport. It can be closed at any time with the ✕ Close Map button (top-right of the overlay) or by clicking anywhere outside the map box.
The map always shows the following layers simultaneously:
| Marker | Colour | Description |
|---|---|---|
| Your QTH | Blue circle | Receiver location extracted from the GPS coordinates in the log row. Tooltip shows lat/lon, reception time, and signal level. |
| Best-match TX | Green circle | The transmitter site selected by the validation algorithm as the most likely identification. A dashed polyline connects it to the QTH. Tooltip shows station name, city, PI, PS, ERP, polarisation, distance, azimuth, and station ID. |
| Alternative TX sites | Red circles | Other transmitters on the same frequency that also match the received PI and PS – i.e. genuinely ambiguous candidates. Each has its own dashed polyline and tooltip. Clicking a red marker opens the Fix dialog for that alternative transmitter (see Section 14.3). |
| Other TX sites | Grey circles | All other transmitters from the current log session (best-match sites of all other rows) that have not already been drawn in green or red. These provide propagation context at a glance. No polyline is drawn; tooltips show station name and distance. |
Hovering over any marker highlights its connecting line (if present) and opens the tooltip. Moving the mouse away restores the default line style.
The map viewport is automatically fitted to encompass all plotted markers with 40 px padding. If only the QTH is available (no TX coordinates found), the map centres on the QTH at zoom level 7.
Clicking a red alternative TX marker opens the Fix from map dialog on top of the map overlay. The dialog shows a summary table of the values that would be written to the row if the alternative transmitter is applied:
| Button | Effect |
|---|---|
| Apply to this entry only | Fixes the current row with the clicked alternative transmitter and re-opens the map to reflect the updated data. |
| Apply to all matching entries | Fixes every row in the log that shares the same frequency and PI code, then re-opens the updated map. |
| Cancel | Closes the Fix dialog and returns to the map without making any changes. |
The ⬇ Download filtered CSV button exports all currently visible rows (i.e. all rows that pass the active filters) to a new CSV file in URDS format with enriched metadata fields.
The following fields are written into the output CSV (all other original fields are preserved unchanged):
| CSV field index | Content written |
|---|---|
| 0 | Record type "30" (always normalised) |
| 13 | PI code (uppercase, no 0x prefix) |
| 15 | PS name (underscores → spaces, 8 characters, original or fixed casing) |
| 30 | Station ID (from fix or as originally present in the log) |
| 36 | Station name |
| 37 | City |
| 38 | ITU country code |
| 39 | ERP in kW |
| 40 | Polarisation |
| 41 | Distance in km (precise float from Haversine formula) |
| 42 | Azimuth in degrees (precise float) |
| 43 | Transmitter latitude |
| 44 | Transmitter longitude |
The output file name is validated_originalfilename.csv.
The 📋 Copy to Clipboard button copies all currently visible rows as CSV text to the system clipboard. The content is identical to what the Download button would produce. This is useful for pasting directly into other tools (e.g. URDS Map Viewer) without creating an intermediate file.
A success toast "Copied N rows to clipboard." or "Copied to clipboard!" is shown after a successful copy. If the Clipboard API is unavailable, an automatic fallback using document.execCommand("copy") is attempted.
Both the Download and Copy to Clipboard functions always produce output rows with exactly 45 fields (indices 0–44). This guarantees that the URDS Map Viewer and other downstream tools always find each value in the expected column position – even when the original CSV had fewer columns.
The Highpoint's Webtools panel is a navigation hub at the very top of the page linking to related tools in the Highpoint toolchain. Hover over the button to expand the panel; it closes automatically when the mouse leaves.
| Tool | Description |
|---|---|
| TEF Converter | Converts raw TEF6686 / TEF6687 CSV output to standard URDS format |
| URDS ID Inserter | Batch-inserts FMLIST station IDs into an existing URDS CSV |
| URDS Uploader | Uploads a URDS CSV directly to your FMLIST account |
| URDS to HTML | Converts a URDS CSV to a formatted HTML reception report with station ID and TX editing capabilities |
| URDS Map Viewer | Interactive map visualisation of URDS CSV files with full statistical analysis |
| FMLIST DX Log Analyzer | Analyses FMLIST logbook export files for DX statistics |
| Sporadic E Monitor | Real-time dashboard for monitoring Sporadic-E propagation activity |
The tool reads URDS (Universal RDS) format CSV files as produced by TEF6686 / TEF6687-based receivers. Each data row must start with a record type indicator. The tool automatically recognises and handles two variants:
Key field positions (0-based index, after the record type field "30" at index 0):
| Index | Content | Example |
|---|---|---|
| 3 | Frequency in Hz | 97300000 → 97.30 MHz |
| 5 | Signal level in dBµV (float) | 39.0 |
| 8 | Receiver latitude (decimal degrees) | 48.585023 |
| 9 | Receiver longitude (decimal degrees) | 7.733249 |
| 11 | Antenna height (metres, float) | 190.04 |
| 12 | Timestamp (ISO 8601 UTC) | 2026-03-22T07:20:36Z |
| 13 | PI code (with or without 0x prefix) | 0xF201 or F201 |
| 15 | PS name (optionally quoted, up to 8 chars) | " INTER " or ACCENT_4 |
| 20 | PTY name (quoted) | "No PTY" |
| 30 | Station ID (FMLIST) | 2502895 |
| 31 | AF list (semicolon-separated) | 97.3;93.1;93.2;95.7 or 9730;9310 |
| 36 | Pre-filled station name | France Inter |
| 37 | Pre-filled city | Strasbourg |
| 38 | Pre-filled ITU country code | F |
| 39 | Pre-filled ERP (kW) | 50.0 |
| 40 | Pre-filled polarisation | H |
| 41 | Pre-filled distance (km) | 18 |
| 42 | Pre-filled azimuth (°) | 288 |
| 43 | Pre-filled TX latitude | 48.64 |
| 44 | Pre-filled TX longitude | 7.49 |
0 or 0.0 are discarded to prevent spurious Gulf-of-Guinea coordinates.
The following diagram shows the recommended step-by-step workflow for processing a URDS log after a DX session:
URDS Log Validator · Documentation v1.2 · Author: Highpoint · March 2026
Part of the Highpoint Webtools Suite · highpoint.fmdx.org/webtools/