Privacy policy
NetRunbook
Last updated October 7, 2026
Who we are
NetRunbook is published by ClickSpark Software. For privacy requests and any other question, write to support@clicksparksoftware.com. Website: https://clicksparksoftware.com
In this policy "we" means ClickSpark Software and "the app" means NetRunbook on iPhone, iPad, Mac (the iPad app on Apple silicon) and Android.
The short version
- We collect nothing. There is no account, no sign-in, no analytics, no crash reporting, no advertising, no attribution or tracking SDK and no server of ours that the app talks to.
- Your data stays on your devices. History, favorites, saved devices, recent targets, saved commands and settings are stored in the app's private storage on the device. Your device's own backup (iCloud Backup or Android backup) can include them; we never see those backups.
- iCloud sync uses your own iCloud, never a server of ours. On iPhone, iPad and Mac, when you are signed in to iCloud, the app keeps your saved devices, favorites, history (saved terminal sessions included), TCP Client quick-send commands, Watchlist items, HTTP Tester saved requests (without their secrets), custom cable pinouts, Network Snapshots, custom Runbooks and Diagnostic Sessions the same on your devices through the app's private storage in your own iCloud account. We cannot read it. Settings, recent targets, the Pro unlock, the introduction, the secrets of saved HTTP requests, saved Network Console sessions and the device history each device builds from your snapshots, scans and investigations are not synced. Settings → iCloud → Sync with iCloud turns it off. There is no sync on Android.
- The app connects to the network when you run a tool, to the targets you type in or to the network you are on. A few tools ask a named public service for an answer (your public IP address, the network an address belongs to). Each one is listed below. Private and other non-public addresses are never sent to a lookup service.
- MAC address lookups never leave the device. The adapter maker shown for a MAC address (MAC Lookup, Network Info, Devices, the Subnet Scanner, the mDNS Browser) comes from a copy of the IEEE registry bundled with the app. No lookup service is asked.
- The HTTP Tester redacts the secrets it can recognise before saving.
Authorization and cookie headers, other secret-looking headers,
passwords in URLs, secret-looking query values, tokens in the URL path
(bot tokens and webhook secrets), secret-looking form fields and the
values of secret-looking keys in JSON request and response bodies
(
password,access_token, …) are replaced with[redacted]/redactedbefore anything is saved, shared, exported, put in history or synced. Bodies that are neither JSON nor form-encoded (plain text, XML, HTML) and headers or fields under names it does not recognise are kept as they were sent and received, and so are terminal sessions you save in the TCP Client, UDP Client or Listener (including anything you typed, such as a password in a Telnet or SMTP AUTH exchange); with iCloud sync on, they sync as they are. - Saved HTTP requests keep their secrets on the device that saved
them. When you save a request in the HTTP Tester (Pro), the values
the rules above recognise as secrets go into the device's own secure
storage (the iOS Keychain, this device only and never iCloud Keychain;
on Android, storage encrypted with a key held in the Android Keystore).
The rest of the request, with those values replaced by
[redacted]/redacted, is what the database, iCloud sync and Export all my data hold. On another device the secrets open blank for you to type again. - Two kinds of connection happen without a tap, and you can turn both off: when the Home screen first shows that you are connected, and when you open Network Info, the app opens and immediately closes one TCP connection to Cloudflare's 1.1.1.1 on port 443 to show whether the internet is reachable. No data is sent over it. Settings → Defaults → Check Internet automatically turns this off. And if you add hosts, URLs or certificates to the Watchlist, the app checks those targets (and only those) when it opens or comes back on screen, at most every 5 minutes; Watchlist → Check when NetRunbook opens turns this off. With iCloud sync, items added on one device are checked by your other devices too, but only once you have opened the Watchlist on that device. Nothing is checked in the background.
- File Sharing serves files only while you run it. It turns the phone into a web and/or TFTP server for devices on your local network, serves only the files you put in its Shared folder, makes no outbound connection, and stops by itself (after 15 minutes by default).
- Bluetooth scanning only listens. BLE Scanner and Find It read the Bluetooth LE advertisements devices around you broadcast. The app never connects to, pairs with or writes to a device, and the results stay in memory.
- Exports are made on your device and go only where you send them. Copy, Share, Send by email, Save to Files, Print and the PDF report (and Settings → Export all my data) are built on the device. Nothing is uploaded to us or to anyone else; the file goes to the app, person, printer or folder you pick. The temporary files are deleted when you close the Export sheet.
- Importing reads only the file you pick. Settings → Data → Import data opens the system file picker; the app reads the file you choose (one made with Export all my data) on the device and uploads nothing.
- A small diagnostics log stays on the device. The app keeps the last 200 errors and warnings it handled (for example a sync that failed or a connection that timed out) with the app version, system version, tool and kind of error, never hosts, addresses, URLs, results or passwords. It is never synced and never sent on its own: About → Diagnostics shows it, and you can email it to us yourself or clear it.
- Purchases go through Apple or Google. NetRunbook Pro (one-time) and the NetRunbook Automation subscription are bought, renewed and cancelled in the App Store or Google Play. We never see your name, email or payment details. The stores give us sales reports.
- Notifications are local and off by default. File Sharing on Android shows an ongoing notification while it shares, and the Watchlist can remind you before a watched certificate expires if you turn that on. Both are made on the device; there are no push notifications and no server.
- You can delete everything in the app: Settings → Data → Delete all app data. Uninstalling the app also removes it from the device.
What the app stores, and where
Everything below is in the app's private sandbox on your device. None of it is sent to us or to anyone else unless you share it yourself. On iPhone, iPad and Mac, iCloud sync also copies the synced items to the app's private storage in your own iCloud account (see iCloud sync below).
1. The database: netwrench.db
An SQLite file named netwrench.db in the app's documents directory
(the file name, like the com.adamjones.netwrench app identifier, keeps the
app's development name; it is internal and never shown in the app):
- iOS / iPadOS / Mac:
<app container>/Documents/netwrench.db - Android:
/data/data/com.adamjones.netwrench/app_flutter/netwrench.db
It holds these tables:
| Table | What a row holds | Written when |
|---|---|---|
history |
Tool, target (host, address, URL or query you entered), port, time, success, a one-line summary, the tool's results as JSON, starred or not | A tool finishes and Auto save history is on (the default), or you save a terminal session. The free tier shows the latest 10 runs plus up to 5 starred ones on a device; older runs are hidden on that device, not deleted (they stay in this table, in Export all my data and in iCloud sync, and show again with Pro or NetRunbook Automation; see hidden_rows). Pro and Automation show everything |
favorites |
Kind (host, port, URL, subnet, DNS query, TCP endpoint, command or tool), label, value, tool, creation time, and its place in your order on Home. An HTTP Tester URL is saved redacted (see HTTP Tester below) | You tap Save / the star, or move a favorite on Home |
saved_hosts |
The devices you add on the Devices tab: name, hostname, IP, ports, notes, tags, the TLS server name (SNI) you set for a saved target, MAC address, vendor (the adapter maker the bundled IEEE table gave for that MAC, or "Private address (randomized)" and similar), last seen, favorite flag. The MAC address is one you typed, one a subnet scan read from the phone's ARP table (Android 7–9 only), or one a Bonjour service announced in its TXT record. Also when NetRunbook first knew the device (first seen) and its identity hints: other hostnames, Bonjour (mDNS) names, MAC addresses and the maker the device was seen with, so a snapshot or comparison recognises it at another address | You save a device; the identity hints and first seen when you save it from the Subnet Scanner or Investigate, or investigate a device you saved (only new names are added) |
console_sessions |
Network Console sessions you chose to save (Pro "Saved sessions"): the name you gave it, the mode (TCP, TLS or UDP client or listener), the target host or address and port (or the local address a listener used), start and end times, the connection settings (TLS server name, certificate validation, auto reconnect, timeout, payload format, line ending, interface), the TLS details read for it (version, cipher, certificate subject, issuer, alternative names, validity, chain and verdict), favorite flag, your notes, and the transcript: every line sent and received, with its time, direction, remote address and bytes. A transcript can contain whatever you typed or the other side sent, passwords included, so this table is kept on this device only: it is never synced to iCloud and never included in Export all my data; you can export one session yourself from its page. Nothing is saved automatically | You tap Save session in the Network Console, or rename, favorite, add notes to or delete a saved session |
quick_send |
Your TCP Client quick-send commands: the text and its place in the list | You add, edit, reorder or remove one |
watchlist |
Your Watchlist items: kind (host, URL or certificate), the target you entered (host or address, URL, or host for a certificate), port, check method (ping or TCP), the name you gave it, the days before expiry to warn, creation time. A URL that carries a password or a secret-looking query value is refused, not saved | You add, edit or remove an item |
watchlist_results |
This device's last 20 results for each Watchlist item: time, up / down / warning, the outcome (reply, refused, timeout, HTTP status, certificate expiry date and whether it was trusted) and the time taken. Never synced: a result depends on the network this device is on | Each Watchlist check |
saved_requests |
HTTP Tester saved requests: the name and collection you gave each one, creation and last-saved times, and the request (URL, method, headers, body, form fields, timeout, follow redirects) with every secret replaced by [redacted] / redacted under the HTTP Tester rules below. The secrets themselves are never in the database (see 1a). A request that arrives from an import file or from another device is cleaned the same way before it is stored |
You save, rename, duplicate, move or delete a saved request (Pro) |
saved_requests_usage |
When each saved request was last opened or saved on this device (for the Recently used order), and whether it ignores certificate errors on this device. Never synced | Opening or saving a saved request |
custom_pinouts |
Your custom cable and adapter pinouts (Cable Pinouts): the name you gave each one, cable or adapter, creation and last-saved times, your notes, and the pinout itself (the connector at each end with its pin count, gender and whether it connects to DTE or DCE, a signal name per pin, and each wire's colour or your colour name and the pins it joins). Nothing about your network or devices is recorded. The reference charts are built into the app and never stored | You save, rename, duplicate or delete a custom pinout (saving is Pro) |
network_snapshots |
Network Snapshots you capture: the name you gave it (if any), when it was captured, the mode (Quick, Standard or Deep), how it ended, and what each part found: the connection type, interface name, this device's IPv4 and IPv6 addresses, subnet, gateway and DNS servers (never the Wi-Fi name or the access point's hardware address); your public IPv4 / IPv6 address and which service answered (only with Include public IP on); the gateway's ping times; each device found on the network (its address, the name reverse DNS gave it, the names it announced over mDNS, its MAC address and adapter maker only where the phone can read them (Android 7–9), its response time, which of the common ports probed were open, the mDNS service types it announced, and the name of the saved device it matched with how sure that match is); each mDNS service (instance name, type, host name, addresses and port; never its TXT record); and, in Deep mode, each configured check (the host and port, whether it was open, the connect time and, for TLS ports, the TLS version, whether the certificate was valid and matched the name, its expiry date and days left, issuer and subject). For each part also whether it was captured, partial, unavailable (and why), failed or not included. The list also keeps the network, gateway and device and service counts | You capture, rename or delete a snapshot. The free tier shows up to 3 on a device; past that, saving one hides the oldest on this device after you agree (it is not deleted: it stays in this table, in Export all my data and in iCloud sync, and shows again with Pro; see hidden_rows) |
runbooks |
Your custom Runbooks (NetRunbook Automation): the name you gave each one, its position in your list, when it was created and last saved, the edit count (version), the built-in Runbook it was copied from (if any), and its definition: the inputs it asks for (names, types, default values such as a host, port or subnet you typed), its variables, and its steps (which tools run, the hosts, ports, URLs and other values you entered for them, the decisions, For Each settings, and the observation and result messages you wrote). It holds no results: running one is a Diagnostic Session. Built-in Runbooks are part of the app and are not stored | You save a Runbook in the Runbook Builder, start one from a template and save it, duplicate, rename, import or delete one |
diagnostic_sessions |
Diagnostic Sessions you create: the title, site / property, target, issue, notes and tags you typed; the status (Healthy, Issues Found, Failed, Cancelled, or no results yet), start and end times, and counts (checks, passed, warnings, failures, items). A session that ran a Runbook also keeps the Runbook's name, version and the exact definition that ran, the inputs you gave it, and everything it measured step by step: each check's target, port and settings with where each value came from, its structured results (for example reachable or not, response times, port states, DNS answers, certificate validity and expiry, HTTP status codes, discovered hosts and their addresses), each decision with the values it compared and the branch it took, the steps skipped and why, every For Each item with its results, the observations and warnings, the result, and notices about limits. Every web address (URL) a run records (in the inputs, each step's settings and results, the messages and the definition that ran) is kept with its user name and password, secret-looking query values and token path segments replaced by redacted, under the HTTP Tester rules below; the request itself goes to the address as you typed it. Sessions saved by versions up to 1.0.0 (55), before runs were recorded this way, are redacted once by the first newer version that opens: every web address in the stored session is redacted by the same rules and the session is saved again as an ordinary edit, so with iCloud sync on the redacted copy replaces the earlier one in this device's iCloud file and on your other devices when they next sync (a device still running an older version keeps its own copy until it is updated). Sessions with nothing to redact are left exactly as they were; a session written by a newer version of the app than the one that opens it is never rewritten. The title, site, target, issue and notes you typed are kept as you typed them. Raw tool output is kept only for top-level checks, not per item; for each item NetRunbook keeps the results the Runbook uses and those its findings are worded from. A session is kept under about 1 MB: a very large run leaves out the step-by-step details of items (devices, ports) without findings, keeping every item's status, observations and result and the whole run's counts, and the session says so. A manual session keeps the tool results you added from History (the tool, target, port, time, success, one-line summary and the tool's own results as stored in History). Both keep the network the device was on when the session started (connection type, interface name, this device's IPv4 / IPv6 address, subnet mask, gateway, DNS servers and whether a VPN was detected; never the Wi-Fi name or the access point's hardware address), the app version, and what it was started for (the port, server name (SNI) and saved device, when given) |
You start a session (with Start Diagnostics, Run or Create Session), add or remove a result, edit its details, or delete it, or it arrives through Import data. A run is saved when it ends, also when you stop it, the app goes to the background or the network changes (with what it measured so far). The free tier shows up to 10 on a device; past that, saving one hides the oldest on this device after you agree (it is not deleted: it stays in this table, in Export all my data and in iCloud sync, and shows again with Pro; see hidden_rows) |
device_observations |
This device's history of the devices it saw, shown as History on a saved device's page, in Investigate and on a discovered device's page: per device and observation, the time, address, hostname, MAC address and maker (where read), response time, the open ports among those checked, mDNS service types, the network, and where it came from (a snapshot, a Subnet Scanner scan or a Host Investigation, and which snapshot). Only devices that answered are recorded; an investigated host that did not answer adds nothing. At most 200 per device. Never synced, never in Export all my data | Each snapshot you save; each finished Subnet Scanner scan (one row per device it found, also after Stop) and each finished Host Investigation of a host that answered, both only while Auto save history is on. Deleting a snapshot deletes the history it added; Clear in a device's History section deletes that device's rows (and those kept under its address); deleting a saved device deletes its rows. When you save a device (or investigate a saved one), the rows kept under its names or MAC address move to that saved device; rows kept only under an address do not, because another device may have used it, and its page shows them apart as a possible match |
sync_outbox |
Which items changed on this device and have not reached iCloud yet: table, item identifier, change stamp, deleted or not (iPhone, iPad, Mac only; empty on Android) | Every change to the ten synced tables above (history, favorites, saved_hosts, quick_send, watchlist, saved_requests, custom_pinouts, runbooks, diagnostic_sessions, network_snapshots) |
sync_meta |
A random identifier for this installation, made by the app (it names this device's iCloud sync file; it is not a hardware or advertising identifier); the iOS identifier-for-vendor it belongs to (see below); identifiers this installation used before; two flags for the next sync; the record that the one-time HTTP Tester redaction (below) has run | The first change; each sync; the first launch of this version |
sync_removed |
For items this device removed without a deletion marker (a marker forgotten after 30 days, or, in versions up to 1.0.0 (62), history trimmed under the free limit): table, item identifier and change stamp, no content, so an older copy on another device is not downloaded again | Each sync |
hidden_rows |
Which Diagnostic Sessions, Network Snapshots and History runs the free limit hides on this device (for sessions and snapshots you agreed when saving one more; for History, the runs beyond the latest 10): table, item identifier, the reason and when; no content. Never synced, never exported. The items themselves stay in their tables | Saving a session or snapshot at the free limit, recording a run on the free tier, or the free tier applying again when a NetRunbook Automation subscription ends; emptied for a table when Pro or Automation is active |
Each row of history, favorites, saved_hosts, quick_send,
watchlist, saved_requests, custom_pinouts, runbooks, diagnostic_sessions and network_snapshots also carries a change stamp (a time, a counter and the installation identifier)
and a deleted flag, used by iCloud sync, and a deleted item also the time
this device deleted or received the deletion. Deleting an item blanks
every one of its fields at once on this device and keeps only the empty
marker, so your other devices learn it was deleted; the marker is removed
from the database 30 days after this device deleted or received it, once
it has been synced (where sync never runs, as on Android, after 30 days). On Android nothing is queued in
sync_outbox and nothing is recorded in sync_removed; the tables exist
and stay empty.
The installation identifier belongs to this installation on this device. When a backup is restored onto another device (or moved with Quick Start), the app sees that the iOS identifier-for-vendor differs and takes a new random identifier, so two devices never write the same sync file. The identifier-for-vendor is read on the device and stored only in this table; it is not sent anywhere, not even to iCloud.
What history results can contain, depending on the tool:
Network Info: your interfaces and addresses, gateway, DNS servers and, if you granted Location, the Wi-Fi network name (SSID) and the access point's hardware address (BSSID).
HTTP Tester: the request you composed (URL, method, headers, body and options), the response headers, redirects and the first 64 KB of the response body, with secrets redacted first:
- the values of the
Authorization,Proxy-Authorization,CookieandSet-Cookieheaders, and of every request or response header whose name containstoken,secret,key,password,auth,session,signature,jwt,assertion,credential,cookieordpop, or has the wordpass,passcode,passphrase,otportotp(in any case), are replaced with[redacted]; a whole header typed into the name field (Authorization: Bearer …) is treated as name and value; - in the URL, in redirect locations and in
Locationheaders, any user name and password (user:pass@), the values of query parameters whose names look like secrets (token,access_token,key,api_key,apikey,password,pass,secret,signature,sig,auth,authorization,session,code,passcode,passphrase,accesskey,privatekey,otp,totp,pinand names containing them; pairs separated by∨) and path segments that hold a token (Telegram bot tokens, Slack, Discord and Microsoft Teams webhook secrets, and any segment of 32 or more letters, digits,_or-with both letters and digits) are replaced withredacted; - form-body fields with such names are replaced with
[redacted], and so are their values in a raw body sent asapplication/x-www-form-urlencodedor shaped like one (name=value&name=value); - in a JSON request or response body, the value of every key with such a
name, at any depth, is replaced with
[redacted]; JSON that does not parse (half typed, a trailing comma, a comment, cut short) has its"name": valuepairs redacted as text.
Request and response bodies that are neither JSON nor form-encoded (plain text, XML, HTML, anything else), other path segments, and headers, parameters and keys under names these rules do not list are kept as they were sent and received. The live screen still shows exactly what you typed; only what is saved, shared, exported or put in history is redacted. When you run a request again from History, the redacted values are left blank for you to type again, with a note saying why.
Test builds up to 1.0.0 (11) saved HTTP Tester history without this redaction, builds up to 1.0.0 (15) did not yet redact JSON or form bodies, and builds up to 1.0.0 (19) did not know URL path tokens, the newer names above,
;pairs, JSON that does not parse or form-shaped text. The first time a newer version opens, it applies the redaction above, once, to every HTTP Tester run already in History, to saved URL favorites, to the HTTP Tester's recent URLs and to saved requests (a value it now recognises in a saved request moves into this device's secure storage, see 1a). A run it changes is saved again as an ordinary edit, so with iCloud sync on the redacted copy replaces the earlier one in this device's iCloud file and on your other devices when they next sync (a device still running an older version keeps its own copy until it is updated). Runs with nothing to redact are left exactly as they were. Runs a device on the free tier had already removed from its own list under the free limit (versions up to 1.0.0 (62)) are no longer on it and are not rewritten there; the device that still holds them redacts them when it updates, and Clear history with Pro or Automation removes them everywhere.- the values of the
TCP Client, UDP Client, Listener: connection details and byte counts; when you choose Save session (Pro "Saved sessions"), every console line you sent and received, as text and Base64. Sessions saved automatically when a connection ends hold the summary only, not the console.
Network Console: when a session ends, its mode, target and port, connection settings, start and end times and byte counts, never a line you sent or received. The transcript is kept only in a session you save yourself (the
console_sessionstable above, this device only).Public IP: your public IPv4 / IPv6 address.
Subnet Scanner: the addresses, names, open ports and latencies it found and, on Android 7, 8 and 9 only, each device's MAC address and adapter maker.
MAC Lookup: the MAC address you looked up and what the bundled IEEE table says about it, or for a pasted list, every MAC address found in it with its maker (not the pasted text itself).
Port Check never stores the SNMP community string you type.
Email & Domain Health: the domain you checked and what each check found (the published MX, SPF, DMARC and, with Pro, DKIM, MTA-STS, TLS-RPT, BIMI and DNSSEC records, web certificate details and the MX hosts' STARTTLS answers).
File Sharing: when sharing stops, one entry with the servers and ports, whether uploads and the password were on, the times, counts and bytes, and up to 50 transfers (file name, direction, the client's address, size, outcome). Never the user name or password.
BLE Scanner and Find It record no history.
If you do not want results kept, turn off Settings → Defaults → Auto save history.
1a. Secrets of saved HTTP requests: the Keychain and the Android Keystore
When you save an HTTP Tester request (Pro), the app splits it with the
same redaction rules as history (above): the values of Authorization,
Proxy-Authorization and Cookie headers and of every other secret
header listed there; the user name and password in the URL, the values
of secret-looking query and fragment parameters and token path segments;
secret-looking form fields; and the values of secret-looking keys in a
JSON or form-encoded body (JSON that does not parse included). Those
values are the secret part; everything else, with placeholders where
the secrets were, is the public part that the saved_requests table
holds. What the
rules do not recognise stays in the public part as typed: plain-text,
XML and HTML bodies, other path segments, and headers, parameters and
keys under names not listed above. The save sheet says so.
The secret part is kept with the origin it was saved for (scheme,
host and port, for example https://api.example.com:443). The secrets
are put back only into a request that still points at that origin: if
the request now points at another host or port, or from https to
http (it was edited on another device, or an imported file with a
newer copy changed it), nothing is filled in and the editor says "The
host changed since this device saved its secrets. Re-enter them." The
certificate switch (Ignore certificate errors) of a saved request is
kept on this device only (saved_requests_usage); it is never synced or
exported, so another device can never turn certificate checks off here.
The secret part of each saved request is stored on this device only, keyed by the saved request's identifier:
- iPhone, iPad, Mac: in the iOS Keychain (service
com.adamjones.netwrench.savedRequests), readable after the device has been unlocked once since it started, this device only (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: not restored to a different device from a backup, not moved by Quick Start) and not synchronizable (never in iCloud Keychain). - Android: in the app's private storage, encrypted (AES-GCM) with a key that is itself protected by a key held in the Android Keystore, which never leaves the device. These files are excluded from Android Auto Backup and device-to-device transfer (see Backups).
The secret part is never written to the database, the iCloud sync files,
Export all my data, any other export or the diagnostics log. A request
that arrives from an import file or from another device is split again
before it is stored, and any secret found in it is thrown away (an
import never writes to the Keychain or Keystore). Opening a saved
request puts the secrets back into the editor on the device that saved
it. On another device (the request arrived by iCloud sync or by Import
data) there are no secrets: those fields open blank with the note
"Secrets are kept on the device that saved them. Re-enter them here.".
Saving there stores the secrets typed on that device on that device; a
field left blank is saved as its placeholder again, so the device that
holds that secret keeps it. Deleting a saved request in the list deletes
its secrets on this device at once. When a request is deleted another
way (a deletion arriving from another device, or Import data's
Replace), the secrets this device kept for it stay for 30 days, so
an edit made elsewhere that brings the request back, or restoring the
backup Replace made, finds them; after that, or when the deletion record
itself is removed, they are deleted the next time the list of saved
requests loads. Delete all app data deletes every one of them. Because iOS keeps Keychain items
when an app is deleted, the first time saved requests are used after the
app is installed again, any secrets an earlier installation left in the
Keychain are deleted (httpTester.savedRequests.secretsInstall, below).
2. Preferences (shared_preferences)
Stored with the platform's preference store: NSUserDefaults in
<app container>/Library/Preferences/ on Apple platforms, and
/data/data/com.adamjones.netwrench/shared_prefs/FlutterSharedPreferences.xml
on Android.
| Key | Holds | Source |
|---|---|---|
settings.appearance, settings.defaultTimeoutMs, settings.defaultPingCount, settings.defaultEncoding, settings.defaultLineEnding, settings.timestampTerminal, settings.autoSaveHistory, settings.autoInternetCheck, settings.hapticFeedback, settings.homeNetwork, settings.onboardingDone |
Your settings | lib/services/settings/settings_service.dart |
snapshots.mode, snapshots.publicIp, snapshots.checks |
The Network Snapshot mode you last chose, whether to include the public IP, and the host:port targets you added for Deep snapshots (up to 16). This device only | lib/features/snapshots/snapshots_controller.dart |
sessions.recentTargets |
The last 8 targets typed into New Diagnostic Session or Quick Session. This device only | lib/features/sessions/sessions_providers.dart |
home.networkCollapsed |
Whether the Network section on Home is collapsed to its header. This device only | lib/features/home/home_controller.dart |
settings.icloudSync |
Whether Sync with iCloud is on (iPhone, iPad, Mac; absent until you change it, which means on) | lib/services/sync/sync_providers.dart |
recents.<tool> (one per tool, for example recents.ping, recents.httpTester) |
The last 8 targets typed into that tool: hosts, addresses, ports, subnets, and for HTTP Tester the URL with its user name, password and secret-looking query values redacted as described above | lib/services/recent_targets/recent_targets_service.dart, lib/features/http_tester/http_tester_controller.dart |
tcp_client.quickSend.mirror, udp_client.quickSend |
Your saved quick-send commands for the TCP Client (a copy of the quick_send table, so the list shows at once) and the UDP Client (up to 24 each) |
lib/features/tcp_client/quick_send_commands.dart |
tcp_client.quickSend, tcp_client.quickSendImported |
The TCP Client list as earlier versions kept it, until it is moved into the quick_send table at the first launch of this version (then deleted), and the record that this was done |
lib/services/sync/quick_send_import.dart |
entitlement.proStatus |
Whether Pro is unlocked, how (purchase or restore) and when. No receipt, no order number, no account | lib/services/entitlement/entitlement_service.dart |
entitlement.automationStatus |
The NetRunbook Automation subscription as the App Store or Google Play last reported it: its state (for example active, grace period, billing issue, expired), the product (the monthly subscription), whether the store reports the current period as an introductory offer (NetRunbook offers none), the store's renewal or end date, whether it renews, when the store last answered, and the random install id (below) of the installation the store answered on. No receipt, no order number, no transaction id, no account. Kept by Delete all app data | lib/services/entitlement/automation_entitlement.dart, lib/models/automation_status.dart |
entitlement.revocationCheck, entitlement.automationLapseCheck |
The time of a first store answer that found no Pro (iPhone, iPad, Mac) or no current Automation subscription (Android; on iPhone, iPad and Mac only once the subscription's end date and the store's grace period have passed), so the app waits for a second answer a day later before acting on it. Only a date. Kept by Delete all app data | lib/services/billing/pro_revocation_guard.dart, lib/services/billing/automation/automation_resolver.dart |
automation.freeExecutionsUsed, automation.trialStartedAt |
How many counted free Automation runs this device has used (the app offers none today: the two free Runbooks are not counted), and, only if an earlier version wrote it, a trial start date the app no longer reads (no trial is offered). This device only, never synced. Kept by Delete all app data | lib/services/entitlement/automation_entitlement.dart |
watchlist.autoCheck, watchlist.expiryReminders, watchlist.usedHere |
The Watchlist's Check when NetRunbook opens switch (absent means on), its Certificate reminders switch (absent means off), and whether the Watchlist has been opened or added to on this device (automatic checks of synced items start only then). This device only | lib/features/watchlist/watchlist_controller.dart, lib/services/watchlist/expiry_reminders.dart |
domain_health.dkimSelectors |
The DKIM selectors you set in Email & Domain Health (absent means the default list). This device only | lib/features/domain_health/domain_health_controller.dart |
httpTester.savedRequests.secretsInstall |
That this installation has removed any saved-request secrets an earlier installation left in the Keychain (see 1a). No content | lib/features/http_tester/saved/saved_requests_controller.dart |
Recent targets are recorded every time you run a tool, whether or not Auto save history is on. They are removed by Delete all app data.
This installation's id. A small file, automation_install.json, in
the app's cache directory (Library/Caches/ on Apple platforms, the app
cache directory on Android) holds a random id this installation made for
itself and the time it made it. It is not tied to you, your device or
your store account and never leaves the device: it is not synced, not
exported, not sent to us or to the stores, and it is not in device
backups (neither system backs up the cache directory). It lets NetRunbook tell
an Automation subscription the store confirmed on this installation from
one restored with a backup from another device, which NetRunbook then trusts
only until the store confirms it here. The system may clear
the cache directory; the app then makes a new id. Delete all app data keeps
it, like the subscription status it belongs to.
3. Export files
Exports are made on the device from the result on screen. Copy as text, Share text and Send by email (the text in the message body) are free; CSV, JSON, the PDF report and Print need NetRunbook Pro. Nothing is uploaded to us or to any server: each export goes only where you send it — the app, contact, printer or folder you choose in the system share sheet, mail composer, print dialog or file picker.
- Files. To share, email, save or print a file (text, CSV, JSON or
PDF), the app writes it to an
exports/folder in its private cache (Library/Caches/exports/on Apple platforms, the app cache directory on Android, offered to the receiving app through the app's own FileProvider). The Export sheet deletes the files it wrote when it closes; any left behind (for example when the app was closed while the sheet was open) are deleted the next time the sheet opens if they are more than an hour old. Settings → Export all my data writes one JSON file the same way and deletes it once the share sheet closes. It holds HTTP Tester saved requests as the database does, with their secrets replaced by placeholders; the secrets in the Keychain / Keystore are never exported. It also holds your custom cable pinouts, your Network Snapshots (not the device history this device keeps), your custom Runbooks and your Diagnostic Sessions. A single Runbook can also be exported on its own as a Runbook file (JSON) from the Runbooks list or the Runbook Builder, written and deleted the same way. A single snapshot, or a comparison of two, can also be exported on its own from its page, and a Diagnostic Session as a report (text, PDF, CSV or JSON with the whole run) from its page. Cable Pinouts' Image (PNG) export draws the diagram on the device and writes the picture to the same folder. Share PEM on a certificate page writes the certificate the same way; on Apple platforms it is deleted when the share sheet closes, on Android by the next sweep. Delete all app data removes the whole folder, everynetrunbook-*oripscope-*file older builds left in the temporary directory, and anynetwrench-*file from a pre-release build. - Send by email opens your mail app's composer (on iPhone and iPad the system composer; on Android the email app you pick) with the subject, the result and the files you chose. The result is the plain text, also laid out as a simple HTML message (the same text, with tables in a fixed-width font so their columns line up); an email app that does not show HTML uses the plain text. The app sends nothing itself: the message goes only if you send it. Without a mail account the system share sheet opens instead.
- The PDF report names the device model (on iPhone and iPad its
name, such as "iPhone Air", from a list built into the app, or the
model identifier, such as
iPhone18,4, for a model the list does not have; on Android the maker and model), system version and app version, and, when Home or Network Info has already read it, the network the device is on (connection type, Wi-Fi name, addresses, gateway, DNS servers). Making a report reads nothing new from the network. Print hands the PDF to the system print dialog (AirPrint, or Android printing). - Redaction and samples. HTTP Tester exports and Copy are redacted the same way as its history. Diagnostic Session reports (text, PDF, CSV, JSON and Copy) redact every web address in them by the same rules, also in a session an earlier version saved before runs were recorded redacted. Sample data shown in demonstration mode is never exported.
4. Import data and the backup it makes
Settings → Data → Import data reads a file made with Export all my data back into the app.
- Reading the file. The system file picker opens (on iPhone, iPad and
Mac the document picker; on Android the system's open-document screen).
The app sees only the file you pick. It copies that file into a private
import/folder in its cache, reads it and deletes the copy at once; the original is only read, never changed. Nothing is uploaded. - Checking it. The whole file is checked on the device before anything is written. A file that is damaged, made by a newer version of the app, or not a data export changes nothing. Items in the file that cannot be read are left out and counted in the preview.
- Where the items go. Imported history, favorites, saved devices, TCP quick-send commands, Watchlist items and HTTP Tester saved requests (without secrets: they open blank on this device until you type them again, and a secret found in a file's saved request, for example one edited by hand, is replaced by its placeholder and thrown away, never stored; the free version imports no saved requests) are written like items you add yourself: on iPhone, iPad and Mac, with Sync with iCloud on, they sync to your other devices. Merge (the default) only adds and updates; Replace deletes those items here first (and, with sync on, on your other devices), so it asks twice. The UDP quick-send list stays on this device. With the free version, the free limits apply to what is imported, and the preview says what is left out.
- The backup before Replace. Before Replace deletes anything it saves
everything it is about to replace as one file in the same format as
Export all my data, in an
import-backups/folder in the app's private Application Support directory (the newest three are kept). It is never synced and never sent; Settings → Data → Backup before last replace restores or shares it. Like the database, it can be part of your device backup. Delete all app data removes it. It holds saved requests without their secrets, like Export all my data; the secrets of requests Replace removed stay in this device's Keychain / Keystore for 30 days (see 1a), so restoring the backup in that time brings the requests back whole.
5. The diagnostics log
A small log of the errors and warnings the app already handles and explains on screen: a tool's network error as shown (for example "timed out" or "connection refused"), an iCloud sync that failed or could not run, a store purchase error, and a failed call into the iOS or Android side of the app.
- What an entry holds: the time, the app version and build, the
system version (for example
iOS 26.0), where it happened (the tool's name,iCloud sync,Purchases, or the system feature), the kind of error (timeout,refused,noAccount…) and, for some errors, one short line of explanation. - What it never holds: host names, IP and MAC addresses, URLs, e-mail
addresses, file paths, identifiers, request or response content, typed
input or passwords. For a tool's error only the kind of error and the
type of failure are kept, never its message; any other text passes
through a redactor that replaces addresses, names, URLs, ids, long
numbers, quoted text and anything after words such as
passwordortokenbefore it is written, and keeps only the first line. - Where it is kept: one file,
diagnostics/diagnostics-log.json, in the app's private Application Support directory: the newest 200 entries, older ones dropping off. It is never synced to iCloud and never sent anywhere by the app. Like the database, it can be part of your device backup. - Who sees it: you. About → Diagnostics lists the entries. Email to support opens your mail composer addressed to support@clicksparksoftware.com with the entries as text; nothing is sent unless you send that message. Clear empties the log, and so does Delete all app data.
6. Kept in memory only, never written
- The TLS certificate and key the Listener uses for TLS mode, generated on the device each time the app runs.
- Live tool output, terminal consoles you have not saved, the Public IP provider switches, and the mDNS type filter.
- The host you are investigating (the target Host Investigation, the Network Console or a tool last used), kept for 30 minutes so the next tool you open is filled in; it is never written to disk, synced or exported.
- Host Investigation results: what ping, DNS, the port check, mDNS and the TLS check found for the host on the page, dropped when you leave it.
- Everything BLE Scanner and Find It see: the devices, their names, identifiers, signal strengths and advertisement data. They are dropped when you leave the tools or close the app, and leave the phone only if you Copy or Export them.
- File Sharing's user name and password, made new at random for each session, and the HTTPS certificate and key it makes on the device for a session in secure mode.
- Sample data shown in demonstration mode (labelled "Sample").
7. Clipboard
The app writes to the clipboard when you tap Copy, and reads it only when you tap a field's Paste button.
8. File Sharing's Shared folder
The files you put in File Sharing (Shared files → Import, or uploads you
allow from the web page, curl or TFTP) are kept in a Shared folder in
the app's documents directory (<app container>/Documents/Shared/ on
Apple platforms, /data/data/com.adamjones.netwrench/app_flutter/Shared/
on Android) until you delete them in the app or with Delete all app data. They are
served only while File Sharing runs, are never synced, never sent
anywhere by the app on its own, and are excluded from device backups
(see Backups). Files you import are copied there by the system file
picker; the originals are not changed.
9. Certificate reminders
If you turn on Watchlist → Certificate reminders, the app schedules
local notifications for the days before a watched certificate expires:
the title says how many days are left, the text names the item (its name
or host) and the expiry date. They are scheduled with the operating
system on the device (iOS UNUserNotificationCenter; Android
AlarmManager, with the schedule kept in a private preferences file,
ipscope_reminders, so it can be put back after a restart) and nothing
goes to a server. Turning the switch off, or Delete
all app data, cancels them.
Backups
The app leaves two things out of device backups: File Sharing's Shared folder (transfer files such as firmware images and configuration backups do not belong in a cloud backup) and the secrets of saved HTTP requests. Everything else follows the platform defaults:
- iPhone, iPad, Mac: the
Documentsfolder (the database) andLibrary/Preferences(the preferences) are included in iCloud Backup and in Finder / iTunes backups when you use them;tmp/is not. The app sets the "exclude from backup" flag onDocuments/Shared/only. Saved-request secrets are Keychain items marked this device only: an encrypted backup can restore them to the same device only, never to another one, and an unencrypted backup does not hold them. It uses no CloudKit, no iCloud Keychain and no iCloud key-value storage; its only use of iCloud is the sync folder described under iCloud sync below. - Android: Android Auto Backup is on. The manifest's backup rules
(
android:fullBackupContent="@xml/backup_rules"andandroid:dataExtractionRules="@xml/data_extraction_rules") excludeapp_flutter/Shared/and the encrypted saved-request secrets (shared_prefs/ipscope_saved_requests.xmland the two flutter_secure_storage files that go with it; their key lives in the Android Keystore, which is never backed up), so the database (app_flutter/netwrench.db) and the preferences (shared_prefs/FlutterSharedPreferences.xml) are included in Google cloud backup when backup is enabled on your device, and in device-to-device transfer; the cache directory is not.
Saved Network Console sessions are in the database, so they are part of these device backups like the rest of it, even though they are never synced to iCloud Drive or put in Export all my data; delete the ones you do not want kept.
These backups are made, stored and protected by Apple or Google under your account with them. We have no access to them. Restoring a backup restores the app's data with it.
iCloud sync (iPhone, iPad and Mac)
NetRunbook can keep your saved devices, favorites, history (saved terminal sessions included), TCP Client quick-send commands, Watchlist items, HTTP Tester saved requests (their public part, see 1a), custom cable pinouts, Network Snapshots, custom Runbooks and Diagnostic Sessions the same on every iPhone, iPad and Mac signed in to your Apple Account. Sync is free, on by default when you are signed in to iCloud with iCloud Drive on, and you can switch it off at any time.
Where the data goes. Each device writes one file,
Documents/sync/<device identifier>.json, into the app's own private
container in your iCloud Drive (iCloud.com.adamjones.netwrench), and
reads the files your other devices wrote there. The container belongs to your Apple
Account. We, the developer, cannot open, read or delete it, and nothing in
it reaches a server of ours. Apple stores it under its own iCloud terms and
privacy policy (with Advanced Data Protection turned on, iCloud Drive is
end-to-end encrypted). The container does not appear in the Files app.
What a file holds. (Since version 56 a device writes its live
Diagnostic Sessions and Network Snapshots to a few extra files next to it,
<device identifier>.<part>.json, gzip-compressed, so a small change
does not upload them again; they hold the same kind of records.) For
every synced item this device created or
changed: the item's fields exactly as the database holds them (see the
tables above, and "What history results can contain", which also applies
here: for example a Wi-Fi name in a Network Info result, or a terminal
session you saved), with its change stamp. A deleted item, deleted on
this device or on another one, is listed only by its identifier, its
stamp and the fact that it was deleted: when a deletion arrives from
another device, this device rewrites its own file the next time it syncs
so the item's content is gone from it too. Likewise, when another device
changes an item later, this device's older copy is dropped from its file.
History that a device on the free tier hides (beyond the free limit)
stays on that device and in its file, so nothing is lost and your other
devices keep it. Clear history on a device with Pro or NetRunbook Automation
removes every run, there too; on the free tier it removes the runs that
device lists and leaves the older ones it hides. The file also names the random installation
identifier, the time it was written, and the device type (iPhone,
iPad or Mac) so Settings can list your devices. Deletion markers stay
in the file (a few dozen bytes each, no content) so that a device you set
up later learns about the deletion too. A local copy of the file this
device last wrote is kept in the app's caches folder, which is not backed
up and which iOS may empty.
What is not synced. The secrets of saved HTTP requests (they stay in
the Keychain of the device that saved them; the synced copy holds
placeholders), when each saved request was last used on a device,
settings (each device keeps its own), recent
targets, UDP Client quick-send commands, the Watchlist's results (each
device checks from its own network) and its two switches, certificate
reminders, the Email & Domain Health DKIM selectors, File Sharing's
Shared folder, the device history each device builds from its snapshots,
scans and investigations (device_observations) and the snapshot capture
choices, the targets
typed into New / Quick Diagnostic Session, saved Network Console
sessions (console_sessions: their transcripts can hold passwords and
tokens), which items the free limit hides on this device
(hidden_rows), the Pro unlock
(the App Store restores it on each device
signed in to the same Apple Account), the introduction, the sync switch
itself and anything kept in memory only.
When it runs. Only while the app is open on screen: at launch, when you return to the app, a few seconds after you change something, when another device's file changes, and when you tap Sync now. Nothing runs in the background. iOS itself uploads and downloads the files, at times it chooses.
Turning it off. Settings → iCloud → Sync with iCloud. Off stops this device publishing its changes and reading the others'; everything already on the device stays, and the file this device wrote stays in iCloud until you remove it. Remove this device's data from iCloud (same section, after you confirm; available whether the switch is on or off) empties this device's file: every item's content is removed and only the content-free deletion markers stay, so items you deleted do not come back on your other devices. It then turns sync off on this device; your other devices keep what they have already synced. If iCloud cannot be reached, nothing changes and you can try again. Signing out of iCloud, or turning iCloud Drive off (for every app, or for NetRunbook alone), also stops sync.
Clocks. Each change carries its device's time. A change stamped more than an hour ahead of this device's clock is held back (and Settings → iCloud names the device) until both clocks agree, so one device with a wrong date cannot take over. Within that hour, the later stamp wins.
Removing everything from iCloud. iOS Settings → Apple Account (your name) → iCloud → Manage Storage (Manage Account Storage on newer iOS) → NetRunbook, then delete its data. This removes every device's file; the data on each device stays until you delete it there.
Android. There is no iCloud sync on Android, and the Android app shows no iCloud setting: Settings › Backup says the data is backed up with your Google account through Android Auto Backup (above), which is how Android keeps a copy.
Network connections
NetRunbook is a network toolkit, so most of what it does is send traffic. The list below is every connection the app makes. Anything not listed here is not made by the app. With iCloud sync on, iOS (not the app) also transfers the sync files to and from Apple's iCloud servers under your Apple Account; see iCloud sync above and F below.
A. The one connection made without a tap: internet reachability on Home and Network Info
| Endpoint | 1.1.1.1, TCP port 443 (Cloudflare) |
| When | Automatically: once per app session, the first time the Home screen shows a connected network (normally right after launch), and once each time you open Network Info while the row has no answer yet. Also when you pull to refresh or tap Refresh on Home, and when you tap Check / Refresh in Network Info. With Settings → Defaults → Show network on Home off, Home makes no check and reads no network details |
| What is sent | A TCP handshake only. The connection is closed as soon as it opens (1.5 s timeout); no bytes of data are sent |
| What Cloudflare can see | Your public IP address and the time, as with any connection |
| What is NOT sent | Anything about you, your device, the app or your network |
| Default | On |
| How to turn it off | Settings → Defaults → Check Internet automatically (settings.autoInternetCheck). With it off, the check runs only when you tap Refresh or Check. It never runs on a timer or when the network changes; a change only resets the row to "Not checked" |
| Code | NetworkInfoService.internetProbeHost / internetProbePort / internetProbeTimeout and autoInternetCheckProvider (lib/services/network_info/network_info_service.dart), PlatformNetworkSources.tcpReachable (lib/services/network_info/network_sources.dart), automatic checks in lib/features/home/home_screen.dart and lib/features/network_info/network_info_screen.dart |
Reading your network details (interfaces, addresses, gateway, DNS servers, Wi-Fi name) is done locally through the operating system and sends nothing.
MAC vendor (adapter maker) lookups are offline. Wherever the app shows
the maker behind a MAC address (MAC Lookup, the access point under the
Wi-Fi BSSID in Network Info, Devices, the Subnet Scanner, the mDNS
Browser), it looks the address up in a table built from the IEEE
Registration Authority's public listings and bundled with the app
(assets/oui/oui.bin). No network call is made and the address is not
sent anywhere; the table is updated only when the app is updated.
The ARP table on Android 7, 8 and 9. During a subnet scan on those
Android versions, after the probes, the app reads the phone's own ARP
table (/proc/net/arp, the list of MAC addresses the phone has just
talked to on your network) once, on the device, to show each found
device's MAC address and adapter maker. Nothing is sent. Android 10 and
later, and iOS, do not let apps read that table, so the app does not try.
A2. The Watchlist's checks when the app opens
| Endpoint | Only the targets you added to the Watchlist, nothing else |
| When | Automatically when the app opens and each time it comes back on screen, at most once every 5 minutes, if the Watchlist has items. Also when you pull to refresh or tap Check now in the Watchlist, and once for an item when you add it. Items that came from another device through iCloud are checked too (the targets added there), but a device starts these automatic checks only after its own Watchlist has been opened once or an item added on it (watchlist.usedHere), so a new device never contacts them at launch on its own. Never in the background and never on a timer while you use other tools; leaving the app stops the run before its next item (checks already under way, up to 4 at once, finish) |
| What is sent | Per item, the same probe the matching tool uses: three ICMP echo requests (Ping), a TCP connect that is closed at once (TCP port), an HTTP GET with User-Agent: NetRunbook Watchlist following redirects (URL; only the status and timing are kept, not the body), or a TCP connect and TLS handshake with the host name (SNI), closed after the handshake (certificate; the same check as Port Check's TLS option) |
| What is NOT sent | Anything about you or your device beyond what any connection to that target reveals (your IP address and the time) |
| Default | On, but nothing happens until you add an item |
| How to turn it off | Watchlist → Check when NetRunbook opens (watchlist.autoCheck); with it off, items are checked only when you tap Check now or pull to refresh |
| Code | lib/services/watchlist/watchlist_scheduler.dart, lib/services/watchlist/watch_probe.dart, lib/features/watchlist/watchlist_lifecycle.dart |
B. Traffic you start by running a tool
These run only while you run the tool, and go to the target you entered or to the network you are on. Host names you type are resolved with your device's normal resolver unless the tool says otherwise. Each goes to a destination you choose, so what that destination does with it is up to its operator.
| Tool | Where it goes | What is sent |
|---|---|---|
| Ping | The host you typed | ICMP echo requests; on Android, if the device blocks ICMP sockets, the system /system/bin/ping sends them |
| Traceroute | The host you typed, and the routers on the way | ICMP echo or UDP probes (ports 33434 and up) with rising TTL; with "Resolve names" (on by default) a reverse lookup of each hop address through the system resolver |
| TCP Ping, Port Check | The host and port you typed | TCP connects; a TLS handshake with the host name (SNI) when TLS is on; or one UDP datagram: empty or your own hex, a DNS query for example.com, an NTP client packet, an SNMPv2c request with the community string you typed (never a default), or an mDNS query. In the app's first outbound connection of a session, one extra untimed connect to the same host and port goes first |
| Port Scanner | The host you typed | TCP connects to each selected port; with "Probe TLS" on, a TLS handshake to each open port |
| Subnet Scanner | Every address in the block you choose (pre-filled with your own network) | One ICMP echo and TCP connects to common ports per address; reverse lookups to your network's DNS servers, or the system resolver if none are known — never to the public fallback resolvers. On Android 7–9 the phone's own ARP table is then read locally for MAC addresses (see above); that sends nothing |
| mDNS Browser | Your local network only (multicast 224.0.0.251 / ff02::fb) |
Multicast DNS queries for advertised service types and for the services themselves. The app only listens and asks; it advertises nothing. "Open in browser" on a found service opens its address in your browser |
| DNS Lookup, Reverse DNS | Your network's DNS servers; if the device reports none, 1.1.1.1 (Cloudflare) then 8.8.8.8 (Google); or the custom server you enter (Pro) |
The name or address you asked about, as a DNS query over UDP 53 (TCP on truncation or when "Use TCP" is on) |
| TCP Client, UDP Client | The host and port you typed (on Android, UDP may also go to a broadcast or multicast address you choose; iOS does not allow either for this app) | Exactly the bytes you send; a TLS handshake when TLS is on |
| Listener | Nothing outbound | Opens a TCP or UDP port on the interface you choose (by default every IPv4 address) so other devices can connect while it runs; replies only with what you type |
| TLS Inspector | The host and port you typed | A plain TCP connect to time it, then a TLS handshake with SNI (and ALPN / version limits you set); nothing after the handshake |
| HTTP Tester | The URL you typed, and any redirect it follows | The request you composed, with User-Agent: NetRunbook HTTP Tester unless you set your own. Certificate checks apply unless you turn on the per-request option to ignore them. In the app's first outbound connection of a session, one extra untimed TCP connect to the same address goes first |
| Network Info | 1.1.1.1:443 when you open it (unless turned off, see A), refresh or check the Internet row |
The same empty TCP handshake as in A |
| Email & Domain Health | Your network's DNS servers (or 1.1.1.1 then 8.8.8.8 if the device reports none); with Pro, also the domain's web and mail servers |
Only when you tap Check. (1) DNS questions over UDP / TCP 53 about the domain you typed: MX, TXT, A and AAAA records of the domain and of its MX hosts, the SPF include and redirect targets, _dmarc.<domain> and its parent domains, and <domain>._report._dmarc.<report-address domain> for external DMARC report addresses; Pro adds <selector>._domainkey.<domain>, _mta-sts.<domain>, _smtp._tls.<domain>, default._bimi.<domain> and DS / DNSKEY with the DNSSEC DO bit. (2) Pro, only when _mta-sts publishes a record: one HTTPS GET of https://mta-sts.<domain>/.well-known/mta-sts.txt (redirects not followed). (3) Pro: one TLS handshake each to <domain>:443 and www.<domain>:443 through the TLS Inspector's native code; no HTTP request. (4) Pro, only with Check MX TLS (port 25) on: a TCP connection to port 25 of up to 5 MX hosts, sending EHLO [<this device's IP address>], STARTTLS and QUIT; no mail is sent |
| Network Snapshot | The network you are on; with Include public IP on, the Public IP services in C; in Deep mode, the targets you added and your saved devices' ports | Only when you tap Capture Snapshot, one part after another: the network details are read on the device; with Include public IP, the Public IP lookups in C; a few ICMP echoes to the gateway; device discovery is the Subnet Scanner's probes of your network (Pro), on a network larger than 1,024 addresses only the 256 around this device; mDNS listening as the mDNS Browser (Pro; Standard and Deep); ICMP echoes (or a TCP connect to a saved port where ICMP is unavailable) to your saved devices on this network that discovery did not find; in Deep mode, a TCP connect to each configured target and saved device port (up to 32), and a TLS handshake with SNI to the open TLS ports (as the TLS Inspector). Stop ends it at once |
| Diagnostic Session | The target and inputs you gave the Runbook, and what its steps derive from them (for example the hosts a subnet scan found, or the addresses a DNS lookup returned) | Only when you tap Start Diagnostics or Run: the Runbook's steps one after another (up to 8 at a time across a run), each the same probes as the tool it uses (Ping, TCP Ping, Port Check, Port Scan, Subnet Scanner, DNS, Traceroute, TLS Inspector, HTTP Tester, mDNS Browser, TCP connect, Public IP, Whois), within the run's limits (at most 1,024 hosts per scan and per For Each, 5,000 checks per run); the network details are read on the device. Stop, going to the background or a change of network ends it at once. A manual session sends nothing: it only stores results you already ran |
| Watchlist | The targets you added | See A2: the same probes when you tap Check now, pull to refresh or add an item |
| File Sharing (Pro) | Nothing outbound: it answers devices on your local network | While you share (it stops by itself, after 15 minutes by default; on Android with notifications off it always stops by itself): a web server (HTTP or HTTPS, port 8080 / 8443 by default) and / or a TFTP server (port 69, or 6969 where 69 is refused) on the Wi-Fi or wired network you choose (with no such network the app asks you to pick one rather than listening everywhere; set to all networks, the web server listens only on the Wi-Fi and wired addresses (and the device itself), never on a cellular or VPN address, and TFTP only on the Wi-Fi or wired address). They serve only the files in the Shared folder. Web uploads and TFTP uploads are two separate switches, both off by default. By default only private and link-local addresses are answered; the web page asks for a user name and password made at random for each session, unless you turn off Require password (you are asked to confirm). Over plain HTTP that password crosses the network unencrypted; HTTPS protects it. TFTP has no password at all: the TFTP allowed clients list only narrows which source addresses it answers, a convenience filter, not authentication (another device on a shared network can send from a listed address), so leave TFTP uploads off on a shared network. TFTP replies go back to the asking device over UDP |
| BLE Scanner, BLE Find It (Pro) | No network connection | The phone's own Bluetooth radio listens for Bluetooth LE advertisements. Nothing is sent to any device: no connection, pairing or write |
| Subnet Calculator, Subnet Designer, IP Converter, CIDR Cheat Sheet, Cable Pinouts, Port Reference, MAC Lookup | Nothing | Offline (MAC Lookup uses the bundled IEEE table; Cable Pinouts its built-in charts) |
When a TLS certificate is checked against the system's trusted certificates (TCP Ping, Port Check, HTTP Tester, TLS Inspector, the Watchlist, Email & Domain Health and ipify below), the operating system's own verification may contact the certificate authority's revocation service, depending on the certificate and the operating system. That is the operating system's behavior, not the app's, and the app sends nothing of its own in it.
Bluetooth (BLE Scanner and Find It). The identifiers shown are the
ones the system gives the app: on iPhone and iPad a per-app identifier
from iOS; on Android one the app derives from the device's address with a
secret made new each time the app starts, so it lasts one launch. Both
change when a device rotates its private address. Bluetooth hardware
(MAC) addresses are never shown, stored or exported. Company and service
names come from a copy of the Bluetooth SIG Assigned Numbers bundled with
the app (assets/ble/); no lookup service is asked. Results are not saved
to History and not synced.
C. Tools that ask a named public service
These run only when you run the tool (Refresh on Public IP, Look up on Whois), and the Public IP lookups also when you capture a Network Snapshot with Include public IP on. The service necessarily learns your public IP address and the time, as with any connection.
Public IP. The providers are tried in order, separately for IPv4 and IPv6; a later one is asked only if the earlier ones failed. You can switch individual providers off under the tool's Advanced section (at least one stays on; the choice lasts until the app closes).
| Order | Provider and endpoint | What is sent |
|---|---|---|
| 1 | Cloudflare: 1.1.1.1 / 2606:4700:4700::1111, UDP 53 |
One DNS question: whoami.cloudflare, type TXT, class CH |
| 2 | Google: ns1.google.com, UDP 53 (its address is looked up first through your network's DNS servers, or 1.1.1.1 / 8.8.8.8 if none are known) |
One DNS question: o-o.myaddr.l.google.com, type TXT |
| 3 | ipify: https://api4.ipify.org?format=json and https://api6.ipify.org?format=json |
One HTTPS GET with no body and no cookies; the user agent is the standard Dart one (Dart/<version> (dart:io)) |
Not sent: any identifier, the app's name, or anything about your device.
Whois and IP Info. One provider is used:
Team Cymru's IP-to-ASN service, over DNS. A domain you type is first
resolved through your network's DNS servers, or 1.1.1.1 / 8.8.8.8 if
none are known; the first public address it resolves to is looked up.
| Provider | Endpoint | What is sent |
|---|---|---|
| Team Cymru IP-to-ASN | DNS TXT questions through the same resolvers: <reversed address>.origin.asn.cymru.com (or origin6.asn.cymru.com for IPv6), then AS<number>.asn.cymru.com |
The address you looked up, and its AS number |
Private and other non-public addresses are never sent. Private
(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), loopback, link-local,
shared CGNAT (100.64.0.0/10), multicast, documentation (192.0.2.0/24,
198.51.100.0/24, 203.0.113.0/24, 2001:db8::/32), unique-local IPv6
(fc00::/7) and the other reserved ranges are not in any public registry,
so the app answers them on the device with the range's name and RFC (for
example "Private address (RFC 1918): not in public registries") and sends
nothing. A domain that resolves only to such addresses is answered the same
way.
The app does not query any registry's RDAP or Whois service. Instead, a result shows a View the full record at ARIN row (or RIPE NCC, APNIC, LACNIC or AFRINIC, whichever registry Team Cymru reports; see E below). The registry's page opens in your browser only if you tap it.
D. App Store and Google Play
The app uses Apple's StoreKit and Google Play Billing through the
in_app_purchase plugin for the one-time Pro unlock (product
com.adamjones.netwrench.pro).
| When | What happens |
|---|---|
| App launch | The app subscribes to the store's purchase updates so a purchase left unfinished earlier is delivered. On iOS this starts StoreKit's transaction listener; on Android it connects to the Google Play Billing service on the device. The app itself sends no request; the store framework may contact Apple or Google as part of its own work |
| You open the Unlock Pro screen, or tap Settings → Pro → Restore purchases | A product query for com.adamjones.netwrench.pro so the store's own price can be shown |
| You buy or restore | The store's own purchase or restore flow |
The NetRunbook Automation subscription (auto-renewing, monthly) goes through the same store frameworks:
| When | What happens |
|---|---|
| App launch, and when you return to the app (at most once an hour) | The app asks the store framework on the device for the subscription's current state. On iPhone, iPad and Mac, StoreKit reads its own transaction records and asks the App Store for the subscription's renewal status (subscribed, grace period, billing retry, expired, refunded, and whether it renews); on Android, Google Play Billing lists the subscriptions that are active for the Google account in the Play Store. Nothing is sent by the app itself; the store framework contacts Apple or Google as part of its own work |
| You open the Automation screen | A product query for the monthly Automation subscription so the store's own price can be shown (there is no other plan and no free trial or introductory offer) |
| You subscribe, restore, or tap Manage subscription | The store's own purchase, restore or subscription management screens. Restore purchases restores Pro and the subscription together; on iPhone, iPad and Mac it may ask Apple to sync your purchases, which can show Apple's own sign-in sheet once |
| While the app is open | Renewals, refunds and approvals that the store reports are read so the subscription's state stays current |
There is no server of ours and no receipt validation on a server: the
result is checked on the device (StoreKit 2 signature verification on Apple
platforms; on Android, a purchase token must be present and the purchase is
then acknowledged), and the outcome is stored in entitlement.proStatus
and, for the subscription, entitlement.automationStatus. The renewal or
end date shown in Settings is the store's own date; the app never decides
on its own that a subscription has ended. If the subscription ends, nothing
you made is deleted: Runbooks, Diagnostic Sessions, history and reports stay
on your device and remain viewable (items beyond the free limits are hidden
on the device until Pro or Automation is active again, never deleted).
Your Apple Account or Google account, payment method and billing details
are handled by Apple or Google under their own privacy policies; we never
receive them.
What the stores give us. Saying "we receive nothing at all" would be false. Apple (App Store Connect) and Google (Play Console) give developers reports of sales, proceeds, downloads and refunds, aggregated by date, country or region and app version. In addition:
- Apple shares crash reports and app usage statistics with developers only from people who have turned on "Share with App Developers" in their device's Analytics settings.
- Google Play shows developers crash and "app not responding" statistics (Android vitals) from devices whose owners allow usage and diagnostics sharing, and lists each Play order (order number, date, product, amount, status) with whatever buyer details Google makes available to developers under its own policies. We use those only to handle refunds and support requests.
We use these reports only to run and fix the app. We do not combine them with anything else, because we have nothing else.
E. Links that leave the app
| Where | What happens |
|---|---|
| Settings → Legal → Privacy policy / Terms of use; About → Product page / Privacy policy / Terms of use | Your browser opens https://clicksparksoftware.com/apps/ipscope/privacy/, .../terms/ or .../marketing/. From then on it is an ordinary visit to our website in your browser. If no browser can open it, the address is copied to the clipboard instead |
| About → Support | Your mail app opens a new draft to support@clicksparksoftware.com with the subject NetRunbook <version> (<build>) on <device model> · <OS and version>. Nothing is sent unless you send it. If no mail app is set up, the address is copied instead |
| Share / Export | The system share sheet opens with the text or file; it goes only where you send it |
| Export → Send by email | Your mail app's composer opens with the result as text and any files you chose; nothing is sent unless you send it |
| Export → Save to Files | The system file picker opens; the file is saved only where you choose |
| Export → Print | The system print dialog opens with the PDF report |
| Whois and IP Info → View the full record at ARIN / RIPE NCC / APNIC / LACNIC / AFRINIC | Only when you tap it: your browser opens that registry's own public lookup page for the address (https://search.arin.net/, https://apps.db.ripe.net/, https://wq.apnic.net/, https://query.milacnic.lacnic.net/ or https://whois.afrinic.net/), chosen from the registry Team Cymru reported. ARIN, RIPE NCC and APNIC receive the address in the page address; for LACNIC and AFRINIC the app copies the address to the clipboard for you to paste into their search. From then on it is an ordinary visit to that registry's website in your browser, under its own terms. The app itself fetches nothing from it |
F. iCloud sync (iPhone, iPad, Mac)
With Sync with iCloud on, the app reads and writes files in its own container in your iCloud Drive while it is open; iOS's iCloud service uploads and downloads them, to and from Apple, under your Apple Account. The app makes no network connection of its own for this, and no request goes to us. See iCloud sync above for what the files hold and how to switch it off.
Third-party software in the app
There are no third-party SDKs that collect data: no analytics, crash reporting, advertising, attribution, sign-in, push notification or remote configuration SDK.
The app is built with Flutter and these packages that talk to the operating system. None of them sends data to its authors or to us; the only network traffic any of them causes is the store traffic in D (in_app_purchase) and the local-network mDNS queries in B (bonsoir).
| Package | Used for |
|---|---|
| in_app_purchase (StoreKit 2 / Google Play Billing) | The Pro purchase and restore |
| network_info_plus | Wi-Fi name, BSSID and addresses, read locally |
| connectivity_plus | Whether you are on Wi-Fi, cellular, Ethernet or VPN, read locally |
| permission_handler | Asking for and checking the Location permission; on Android, the Bluetooth (Nearby devices) permission for the BLE tools; opening the app's system settings page (notification permission goes through the app's own notify.* native code for both File Sharing and the reminders) |
| bonsoir | Browsing mDNS (DNS-SD) services on your local network |
| package_info_plus | The app version shown on About and in the support email subject |
| device_info_plus | The device model and OS version in the support email subject and the PDF report; on Android, the Android version, to know whether the ARP table may be read (Android 7–9) |
| url_launcher | Opening web links in your browser and the support email draft |
| share_plus | The system share sheet |
| Laying out the PDF report on the device | |
| printing | The system print dialog for the PDF report |
| sqflite | The on-device database |
| shared_preferences | The on-device preferences |
| flutter_secure_storage | Keeping the secrets of saved HTTP requests in the iOS Keychain (this device only, not synchronizable) and in Android Keystore-protected storage (see 1a) |
| path_provider | Finding the app's documents and temporary folders |
iCloud sync uses Apple's own iCloud Drive and file coordination APIs directly, through the app's code; no third-party package is involved.
The rest (flutter_riverpod, go_router, basic_utils, pointycastle, crypto, uuid, intl, lucide_icons_flutter, and the bundled JetBrains Mono font) run entirely inside the app and make no connections. The bundled MAC vendor table is data from the IEEE Registration Authority's public listings (credited, with its date, under About → MAC vendor data and Open-source licenses); it is read on the device only. The bundled Bluetooth company and service names are data from the Bluetooth SIG Assigned Numbers (credited, with their date, under About → Bluetooth names and Open-source licenses), also read on the device only. File Sharing's web and TFTP servers, the Watchlist's probes and Email & Domain Health's DNS, HTTPS and SMTP checks are the app's own code (Dart sockets and the native TLS inspector); local notifications use Apple's and Android's own notification APIs directly.
Permissions
| Permission | Platform | Why | If you refuse |
|---|---|---|---|
| Local Network | iOS / iPadOS 14+ | Reaching devices on your network (scans, ping, connections, mDNS). The system asks the first time a tool touches the local network | Tools that reach devices on your local network cannot reach them; tools that reach the internet, and the offline calculators, still work. Change it in iOS Settings → NetRunbook, or from Settings → Permissions → Local Network in the app |
| Location (while using) | iOS and Android | Both systems reveal the Wi-Fi network name (SSID) and access point (BSSID) only to apps with location permission. The app asks only when you tap to show the Wi-Fi name on Home, Network Info, or Settings → Permissions → Location. It never reads, records or sends your location | Everything works; the Wi-Fi name and BSSID show as hidden |
| Access Wi-Fi Information (entitlement, no prompt) | iOS | Required by Apple, together with Location, for the Wi-Fi name | — |
| iCloud Documents (entitlement, no prompt) | iOS / iPadOS / Mac | iCloud sync through the app's private iCloud Drive container | Sync stays off while you are signed out of iCloud or iCloud Drive is off; everything else works |
| INTERNET, ACCESS_NETWORK_STATE, ACCESS_WIFI_STATE, CHANGE_WIFI_MULTICAST_STATE | Android (granted at install, no prompt) | Opening connections; reading network state and Wi-Fi details; receiving multicast for mDNS | Not refusable |
| ACCESS_FINE_LOCATION / ACCESS_COARSE_LOCATION | Android | The Wi-Fi name, as above | As above |
| NEARBY_WIFI_DEVICES | Android | Not requested. It covers Wi-Fi scanning and peer-to-peer, not the connected network's name | — |
| com.android.vending.BILLING | Android (no prompt) | Google Play purchases | Not refusable; without Google Play, purchases are unavailable and the free tools still work |
| Bluetooth | iOS / iPadOS | BLE Scanner and Find It listen for Bluetooth LE advertisements. iOS asks the first time you start a scan | The BLE tools say Bluetooth access is off and how to allow it in iOS Settings → NetRunbook; everything else works |
| Nearby devices (BLUETOOTH_SCAN, BLUETOOTH_CONNECT) | Android 12+ | BLE Scanner and Find It. Scanning is declared neverForLocation: the app derives no location from it and asks for no location to scan. Because of that, Android 12 and later do not pass iBeacon and Eddystone advertisements to the app (iPhone does not pass iBeacons either); the app decodes beacon data only when the phone shares it. CONNECT is used only to read the name the system already knows for a device; the app never connects. Asked the first time you start a scan |
As above |
| Location (BLUETOOTH, BLUETOOTH_ADMIN and location) | Android 7–11 (API 24–30) | Those Android versions allow Bluetooth scanning only with location permission. The app asks for it when you start a scan and does not use your location | As above |
| Notifications | iOS (alerts and sounds; no badge); Android 13+ (POST_NOTIFICATIONS) | The Watchlist's certificate reminders (asked when you turn them on); on Android also File Sharing's ongoing notification while it shares (asked when you start sharing) | No reminders; on Android, File Sharing still runs without the notification, the screen says so, and Stop sharing after → Never is not offered, so a session always ends by itself |
| FOREGROUND_SERVICE, FOREGROUND_SERVICE_DATA_SYNC, WAKE_LOCK | Android (no prompt) | Keeps File Sharing's local server running with the screen off while it shares, with an ongoing notification and a Stop action. It stops when you stop sharing, when its timer runs out or when the app is closed | Not refusable |
| RECEIVE_BOOT_COMPLETED | Android (no prompt) | Puts the scheduled certificate reminders back after a restart (Android forgets them) | Not refusable; nothing runs at start-up unless reminders are on |
The app does not ask for contacts, photos, camera, microphone, tracking (App Tracking Transparency) or background location. It has no background mode on iOS: nothing runs when the app is not on screen (a file transfer in progress may get a short moment to finish).
Accounts and deleting your data
There are no accounts, so there is no account to delete and nothing held by us about you.
To delete everything the app has stored:
- Open the Settings tab (the last tab in the bottom bar).
- Scroll to the Data section.
- Tap Delete all app data.
- Confirm with Delete everything.
This empties every table of the database (history, favorites, saved
devices, quick-send commands, the Watchlist and its results, HTTP Tester
saved requests, custom cable pinouts, Network Snapshots and the device
history they built, custom Runbooks, Diagnostic Sessions, saved Network
Console sessions and their transcripts, and the sync bookkeeping, including
this installation's
identifier), deletes every saved request's secrets from the Keychain /
Android Keystore storage, compacts the
database (SQLite VACUUM, so
deleted rows do not linger in unused space), clears every preference
(settings, recent targets and both saved quick-send lists), empties the
diagnostics log, deletes the backups Import data made before a Replace,
stops File Sharing and deletes its Shared folder with every file in it,
cancels scheduled certificate reminders and removes the shared files the
app left in the temporary folder. A Diagnostic Session
still running is stopped and not saved, an unsaved new Runbook is
dropped, and every list the app keeps in memory (including saved Network
Console sessions, Diagnostic Sessions, Network Snapshots, device history
and Runbooks) is empty straight away, without restarting the app. A few values are kept
so the app keeps working as you set it up: the record that you finished
the introduction, the Pro unlock status and the NetRunbook Automation
subscription status the store last reported, with their store-check
bookkeeping (the purchases themselves belong to your Apple or Google
account and can be restored at any time), the device's count of free
Automation runs, and whether Sync with iCloud is on. Not affected: copies you shared or exported to
other apps, and device backups made before you deleted.
On iPhone, iPad and Mac (whether Sync with iCloud is on or off), Delete all app data first empties this device's sync file in your iCloud Drive to its content-free deletion markers (as Remove this device's data does; a sync in progress is stopped first) and turns Sync with iCloud off on this device, so the items from your other devices do not download straight back. Your other devices keep their copies until you delete them there (Delete all app data on each device). To remove every device's file from iCloud at once: iOS Settings → Apple Account → iCloud → Manage Storage → NetRunbook. If iCloud cannot be reached at that moment, the app deletes everything on the device, tells you the iCloud copy could not be emptied, and you can remove it in Manage Storage.
Smaller steps in the same section: Clear history and Clear favorites. With iCloud sync on, they remove the items on your other devices too. With Pro or NetRunbook Automation, Clear history removes every recorded run, including history an earlier version of the app removed from this device under the free limit that your other devices still keep. On the free tier it removes the runs listed in History; older runs beyond the free limit are not deleted: they stay on this device, hidden until Pro or Automation is active, and on your other devices. Single history items, favorites and saved devices can be deleted where they are listed.
Uninstalling the app deletes all of its on-device data, including the Pro status and temporary files. On iPhone, iPad and Mac, iOS itself may keep Keychain items after an app is deleted; the secrets of saved HTTP requests are deleted the first time saved requests are used after the app is installed again (see 1a), or delete them before uninstalling with Delete all app data. A sync file already in your iCloud Drive stays there until you remove it in Manage Storage (above).
For Google Play's data-deletion requirement, the page https://clicksparksoftware.com/apps/ipscope/delete/ gives these same steps. Because we hold no data about you, there is nothing for us to delete on request; if you write to us, we will confirm that.
Your rights
Data protection laws give you rights to access, correct, delete and port your personal data and to object to its use. Because we do not collect or hold personal data through the app, the data those rights apply to is on your device (and, with iCloud sync, in your own iCloud account) and under your control, as described above. For data held by Apple or Google about your purchases, contact them. You can contact us with any question or privacy request at support@clicksparksoftware.com, and you may complain to your local data protection authority.
Children
NetRunbook is a professional tool for IT technicians and is not directed at children. It collects no personal data from anyone, children included.
Changes to this policy
When the app's behaviour changes, this policy is updated in the same release and the "Last updated" date changes. The app shows no notice of policy changes itself; the current version is always at https://clicksparksoftware.com/apps/ipscope/privacy/, which Settings → Legal → Privacy policy opens.
Contact
ClickSpark Software Privacy requests and questions: support@clicksparksoftware.com https://clicksparksoftware.com/apps/ipscope/support/
