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 (Web version only) |
| Process from Clipboard | Yes | Reads URDS log text directly from the clipboard (Web version only) |
| Show Filters / Hide Filters | Yes | Toggles the filter bar visibility |
| No import duplicates (checkbox) | Yes | Discards duplicate Freq+PI+PS combinations on import |
| No validate AI RDS (checkbox) | Yes | Toggles the usage and visibility of AI-enhanced RDS data during validation. |
| ⚡ 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 (Web version only) |
| 📋 Copy to Clipboard | After validation | Copies currently visible rows as CSV text to the clipboard (Web version only) |
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.
<br> tags for line breaks instead of proper newlines), the validator automatically cleans these tags up to preserve your exact PS spacing and parse the rows correctly.
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 kept. If a subsequent duplicate contains a valid Station ID while the previously imported one did not, the system will automatically upgrade to the entry with the ID. Speeds up processing of long overnight logs significantly. |
The TEF Logger App (version 6.0 and later) or the RDS AI Decoder for the FM-DX Webserver can provide AI-processed PI and PS values. The "No validate AI RDS" checkbox controls how this AI data (which is provided in fields 45–47) is handled during validation:
| State | Behaviour |
|---|---|
| ☐ Unchecked (default) | The validator uses the AI PI and AI PS columns in the background to achieve much higher accuracy when matching against the database. However, your originally logged standard PI and PS are strictly preserved and displayed in the main UI table to keep your log physically accurate. The extended detail row will use the AI PS for variant checks to explain its matching logic. |
| ☑ Checked | AI processing is completely disabled. The AI RDS, AI PI, and AI PS columns are instantly hidden from the table, and the validation engine falls back to using exclusively your standard raw logged PI/PS values for all database matching. |
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. Note: The 0x prefix is hidden in the UI for readability but is strictly preserved upon export. |
| PS | CSV field 15 | Programme Service Name (8 characters). Spaces shown as underscores (_). A single ? is automatically treated as an empty PS. If the PS is a partial match, it appears in orange text, and red if it is a complete mismatch (evaluated independently of the AI PS). Underlined when corrected. Note: Underscores are fully preserved and will not be converted to spaces in the exported CSV. |
| 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 (this warning is AI-aware and intelligently uses your AI PI/PS data to calculate conflicts if AI validation is enabled). |
| 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. |
| AI RDS | CSV field 45 | Artificial Intelligence evaluation flag (1 = active, 0 = inactive). Can be hidden dynamically using the "No validate AI RDS" checkbox. |
| AI PI | CSV field 46 | AI-processed PI code. Used for database matching if AI validation is active. Hidden if disabled. Note: Any 0x prefix is automatically stripped in the UI view for a cleaner look. |
| AI PS | CSV field 47 | AI-processed PS name. Used for database matching if AI validation is active. Invalid matches are highlighted in bold red, and partial matches in orange. Corrected values are underlined, and hovering shows the original AI PS snapshot. Hidden if disabled. |
| Comment | CSV field 48 | User comments. This column is inline-editable. Tap the cell to type or modify your comment directly in the table. Changes are saved automatically upon export. |
| 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. Missing IDs cap the score at 74. |
| 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. If an exact match fails, a fuzzy alphanumeric fallback is used (matching only letters and numbers, ignoring punctuation, hyphens, and spaces). |
| 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 | 74–100 |
| Level 2 | Freq + PI match, PS not in DB variants | 40–73 |
| 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 | ≥ 74 | Good match – PI, PS and usually AF confirmed. High confidence identification. |
| Yellow | 40 – 73 | 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 ≥74% (green) 55 40–73% (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 ≥74% | Mini ring gauge (36×36 px canvas): number of non-fixed rows with score ≥ 74. The ring fill proportion represents the share of all rows. The number is drawn centred inside the ring. |
| Ring 40–73% | 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 |
| ≥ 74% 🟢 | Score ≥ 74 (green rows) |
| 40–73% 🟡 | Score 40–73 (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 (🟢 ≥74%, 🟡 40–73%, 🔴 <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 features an interactive Radius Range slider that allows filtering rows based on their distance from the receiver to the transmitter:
| Element | Description | Typical use |
|---|---|---|
| Radius Range Slider | Slide both handles to define minimum and maximum distance (e.g. 150 km - 700 km). | Precisely fine-tune visibility based on distance bands (e.g., suppressing local stations or focusing strictly on Sporadic-E catches above 1300km). |
Only rows whose calculated distance falls within the selected slider range will be displayed. If the maximum handle is pulled all the way to the right, it equates to "Infinity" (∞ km), placing no upper limit on the distance.
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 slider positions 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 / Red | Whether the received PS matches any known DB variant. Green for an exact full match. Orange if it is a partial match (alignment differs or fuzzy alphanumeric match). Red if it is completely absent from the DB variants. |
| 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. "AF check bypassed" is shown if the reception is a perfect unique match. |
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 table includes the calculated distance (Dist) to each transmitter, and you can click on any column header to sort the list. 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" pre-filters the candidate list to entries that match the PI code. Uncheck it to see all transmitters on this frequency. By matching only the PI and ignoring the PS, the tool easily handles instances where your receiver captured an incomplete PS fragment or dynamic text. The dropdown starts with an empty default option—you must actively select a transmitter from the list to prevent accidental wrong assignments. The transmitter list is sorted by ascending distance from the receiver (nearest first). Each entry shows station name, city, PI, PS, ERP, ITU code, calculated distance in km, and calculated azimuth in degrees.
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. You can also choose the "Leave PS empty" option to clear the PS field, or 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). Distance and azimuth are dynamically recalculated based on the selected transmitter's coordinates. 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). Manual PS selections will successfully overwrite the logged PS to allow manual overrides. |
| 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 matching. |
| 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. |
Clicking this button generates a new CSV file containing all currently visible FM rows. Crucially, the export strictly preserves the exact chronological sequence of your original log file. This means any non-FM lines (such as file headers like 10, 11 or DAB logs starting with 20, 21) are kept completely intact and are written back exactly where they appeared in the original file.
For the FM data, it exports exactly what is shown in the table (meaning all active filters, like distance limits or "Hide unidentified", apply to the exported FM rows). The exported file is named validated_{original_filename}.csv.
Copies the filtered, enriched CSV data directly to your system clipboard, maintaining the exact same sequential preservation of headers and non-FM logs as the file download. You can immediately paste this into Excel, a text editor, or directly into the FMLIST manual upload page.
Whether downloading or copying to clipboard, the tool ensures every row has exactly 49 columns (including the Comment column), padding empty fields with commas. This guarantees strict compatibility with the FMLIST Upload portal and preserves RAW data perfectly.
When the URDS Log Validator is launched directly from within the TEF Logger App on a smartphone, it operates in a special integrated mode optimized for mobile workflows:
At the very top of the page, a collapsible panel links to the entire suite of Highpoint's FM DX web tools (such as the TEF Converter, URDS ID Inserter, Map Viewer, etc.).
The tool parses standard URDS format. While the validator specifically processes and visualises FM log entries (Record type 30), it safely reads and preserves all other record types (e.g., headers, AM/DAB logs) in the background. The crucial fields for the FM validation are: