Skip to content

Watchlist deep links

A watchlist deep link is a URL that carries a list of Wi-Fi networks. Opening it adds those networks to the Wi-Fi watchlist, which makes it easy to share a curated list with someone else.

This page documents the URL format precisely so that anyone can generate their own links. The link is a verified Android App Link for the networksurvey.app domain.

  • On Android with Network Survey installed, the app opens its Watchlist page (the same page as More > Tools > Watchlist) and shows a confirmation prompt to add the networks.
  • Otherwise (the app is not installed, or the link is opened in a desktop browser), the link loads a page on networksurvey.app that previews the networks in the list and offers a button to open the app, along with links to download it.
https://networksurvey.app/app/watchlist?d=<base64url-json>
PartValue
Schemehttps
Hostnetworksurvey.app
Path/app/watchlist
Query parameterd (the encoded payload)

The single d parameter holds the entire payload. No other parameters are read.

The value of d is a JSON document that has been encoded as follows:

  1. Serialize the payload to JSON and encode it as UTF-8 bytes.
  2. Encode those bytes with base64url (the URL-safe alphabet from RFC 4648, which uses - and _ in place of + and /).
  3. Produce the value with no padding (omit any trailing =) and no line wrapping.

Additional requirements:

  • Use the URL-safe alphabet. The app decodes d as base64url only, so a value that contains standard base64’s + or / cannot be read and the link will not import. (The web preview page is more lenient, so a link that previews on the web can still fail in the app.)
  • Do not compress the JSON. The payload is plain UTF-8 JSON.
  • Because base64url uses only URL-safe characters, the value needs no additional percent-encoding when placed in the query string.
  • The encoded d value must be at most 16 KB (16384 characters).

The JSON payload is an object:

{
"v": 1,
"name": "Acme networks",
"entries": [
{ "label": "HQ", "ssid": "HQ-Guest" },
{ "label": "Lobby", "bssid": "a4:11:22:33:44:1c" }
]
}
FieldTypeRequiredNotes
vintegerYesSchema version. Must be exactly 1.
namestringNoA name for the list, shown in the import prompt. Maximum 100 characters. When absent or blank, a generic prompt title is used.
entriesarrayYesThe networks to add. Must contain 1 to 100 entries.
entries[].labelstringNoA display name for the entry. When absent, the app falls back to the SSID, then the BSSID. Maximum 100 characters.
entries[].ssidstringNo*The Wi-Fi network name. Maximum 32 characters. Case is preserved but matched case-insensitively.
entries[].bssidstringNo*An access point MAC address in the form XX:XX:XX:XX:XX:XX. Case-insensitive; stored in lower case.

* Each entry must include at least one of ssid or bssid.

  • An entry with only an ssid matches any access point broadcasting that network name.
  • An entry with only a bssid matches that specific access point.
  • An entry with both ssid and bssid matches only when both are seen together (logical AND). To match on just one field, include only that field.

An entry with neither ssid nor bssid has nothing to match and is skipped.

Every value is validated before anything is imported. Validation is all or nothing: if any value is out of bounds (for example a malformed BSSID or an over-long SSID), the entire link is rejected rather than partially imported or truncated. The one exception is an entry with no identifier at all (neither ssid nor bssid), which is simply skipped; if that leaves no valid entries, the link is rejected.

RuleLimit
vMust equal 1
Number of entries1 to 100
ssid lengthUp to 32 characters
label lengthUp to 100 characters
name lengthUp to 100 characters
bssid formatMust match ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$
Encoded d lengthUp to 16 KB

Control characters and Unicode format characters (for example zero-width spaces) are stripped from the name, label, and ssid text.

When a valid link is opened:

  • The app always shows a confirmation prompt before saving anything.
  • The import merges into the existing watchlist. Only networks that are not already present are added; duplicates (matched case-insensitively on SSID and BSSID, including repeats within the link) are skipped, and existing entries are never modified.
  • Confirming the import enables the watchlist feature.

The following payload:

{"v":1,"name":"Acme networks","entries":[{"label":"HQ","ssid":"HQ-Guest"},{"label":"Lobby","bssid":"a4:11:22:33:44:1c"}]}

encodes to this URL (whitespace in the JSON is insignificant; the example above is minified):

https://networksurvey.app/app/watchlist?d=eyJ2IjoxLCJuYW1lIjoiQWNtZSBuZXR3b3JrcyIsImVudHJpZXMiOlt7ImxhYmVsIjoiSFEiLCJzc2lkIjoiSFEtR3Vlc3QifSx7ImxhYmVsIjoiTG9iYnkiLCJic3NpZCI6ImE0OjExOjIyOjMzOjQ0OjFjIn1dfQ

You can use this example to verify that your encoder produces the same d value.

If a link cannot be imported, the app shows a short message and imports nothing. For example, a link with a newer schema version than the installed app understands shows a message that a newer app version is needed. Malformed or oversized links show a corresponding error message.

  • Wi-Fi watchlist: what the watchlist does and how to use it
  • Intent API: the other programmatic integration for Network Survey