Every finance app gets asked the same question eventually: where does my data go? The two answers people are used to are a privacy policy nobody reads and "trust us." Neither is good enough for software that holds your brokerage history.
Below is every internet address the Pyx desktop app can reach, nine of them as of version 0.2.12, with what each request carries, what it never carries, and a check you can run on your own Mac in about ten minutes without trusting a word of this.
Nothing here needs a technical background. Every term is explained the first time it appears, and the one section written for engineers is marked so you can skip it.
A host is an address, and nine is the whole story#
A host is an address on the internet, like query1.finance.yahoo.com. A program can only send information to addresses it names. So if you know every address a program can name, you know everywhere its data can go.
Most software handles this the way a bouncer with a wanted poster would: let everyone through, stop the ones that look wrong. Pyx works from a guest list. The app carries a short, fixed list of addresses, and a request to any address that is not on the list is refused before it is sent. Not caught afterward, not logged and allowed. Refused.
For the engineer: the list is a hash set in crates/data/src/net/allowlist.rs, every HTTP client the app creates is built through it, and the release build has no code path that can add to it. The mechanism gets its own section further down.
The rule matters more than the number#
Nine is the count today. It will change as Pyx adds data sources, so the number is worth less than the rule behind it. The rule has three parts.
Every address Pyx can reach is written into the app and published, here and in the privacy policy, with what it is for. Nobody can type a new address into the app, including you. And the only addresses that are on by default are the ones a feature you chose needs: prices need Yahoo, linking a brokerage needs SnapTrade, subscribing needs the license service, opening a company's research page needs the SEC.
As new sources are added, each one will be a fixed address published in the same table, it will start off, and it will have its own switch, with a sentence saying what that source can see. A per-ticker data provider, for example, sees the symbols you look up. The base set stays small.
A list of nine you cannot change is a fact about this version. A rule that every future address is published, off by default, and yours to turn on is a fact about every version after it. Hold Pyx to the rule.
The nine hosts, as of 0.2.12#
| Host | Run by | When Pyx contacts it | What the request carries | What it never carries |
|---|---|---|---|---|
query1.finance.yahoo.com | Yahoo | Prices, price history, exchange rates | The ticker symbols and currency pairs on screen | Quantities, values, your name |
query2.finance.yahoo.com | Yahoo | Quotes, company fundamentals | Ticker symbols | Same |
fc.yahoo.com | Yahoo | Once, to collect a consent cookie Yahoo requires before it answers profile questions | Nothing beyond the request itself | Anything about you |
api.snaptrade.com | SnapTrade | Only if you link a brokerage | A signed request with a random per-install id | Your brokerage password, ever |
license.pyx.finance | Pyx (Cure AI) | Only if you subscribe | First activation: the license key, the app version, the operating system name. Every later check: the key alone | Your portfolio, your email |
pyx-license.fly.dev | Pyx (Cure AI) | Fallback address for the same service | Same as above | Same |
www.pyx.finance | Pyx (Cure AI) | About once a day, to ask for the newest version number. And once, when you click Update | Daily: nothing. Update click: the license key | Anything else |
release-assets.githubusercontent.com | GitHub | Only after you click Update, to download the package | A link that expires | Anything beyond the link |
data.sec.gov | U.S. SEC | When you open a company's research page | The company's public id number, plus the app name, version, and support email in the request header | Anything about your holdings |
Every request also carries what any internet request carries: your IP address. There is no way to send a request without one, and the policy says so plainly.
Here is each service in the order a new user meets them.
Yahoo Finance, three addresses. Every price, chart, and exchange rate in the app comes from Yahoo. A request carries the ticker symbols you are looking at and, for multi-currency portfolios, the currency pairs. It does not carry how many shares you own, what they are worth, or who you are. The third address, fc.yahoo.com, exists because Yahoo hands out a small token before it will answer questions about a company's sector or an ETF's holdings; Pyx collects it once and reuses it. One more detail, because anyone watching the traffic will see it: Yahoo answers only requests that look like they came from a web browser, so Pyx identifies itself to Yahoo with a generic browser signature. It says nothing about you or your machine.
SnapTrade, one address. Pyx never contacts SnapTrade unless you link a brokerage. When you do, you log in on SnapTrade's own page in your web browser, and Pyx never sees the password. What the app keeps is a random id for your install and a secret, sealed in a file only your Mac's keychain can open, and every request is signed with that secret so SnapTrade knows it came from your copy. The part worth reading twice: the SnapTrade code inside Pyx holds a fixed table of the five kinds of question it can ask (accounts, positions, options, balances, activity), and it refuses to form any other request before touching the network. There is no "place an order" request in the app to be triggered. Read-only is not a promise, it is the shape of the code. What SnapTrade itself sees is covered by SnapTrade's privacy policy.
The license service, two addresses, one service. Pyx is free to use with imported or hand-entered data. If you subscribe for brokerage sync, in-app updates, and agent access, the app talks to the license service. The first time, it sends three things: the key, the app version, and the operating system name. Every later check sends the key alone. The service keeps no database and does not write the key to its logs; it asks Polar, the payment provider, whether the subscription is active and hands back a signed note that the app can check on its own, without asking again, for 35 days. The second address is a fallback for the same service in case the first one's domain has a bad day. Nothing about your portfolio ever goes to either.
The Pyx website, one address. About once a day the app asks the website one question: what is the newest version? The request carries nothing about you. There is no setting to turn that check off, and I would rather say so here than have you find it. When you click Update, a single request carries your license key so the site can hand back a download link.
GitHub, one address. The update package itself downloads from GitHub's release servers, only after you click Update, from a link that expires. Before anything installs, the file is checked against a published fingerprint and against Apple's code signature, so a tampered package fails and a real one passes.
The SEC, one address. When you open a company's research page, Pyx fetches its filings index and ten years of financial statements from EDGAR, the SEC's public database. The request carries the company's public id number (Apple's is 320193) and, because the SEC requires every program to introduce itself, a header naming the app, its version, and a support email. Never anything about your holdings. The filing documents themselves open in your browser, not inside the app.
What is not on the list#
The things people assume a finance app does, and Pyx does not:
- No analytics, no crash reporting, no telemetry. There is no such library in the app. Not disabled, not opted out: absent from the code, so even a bug could not phone home to one.
- No payment processor. Subscribing happens in your browser at Polar. The app never contacts Polar and never sees a card.
- No AI service. Turning on agent access opens a socket on your own Mac for tools like Claude Code and adds no addresses to the list.
- Not even the obvious neighbors.
pyx.financewithout thewwwis excluded, because it redirects and redirects are refused.www.sec.govis excluded, because filing documents open in your browser.
How the list is enforced#
Skip this section if you only want to run the check. It is here for the reader who wants the mechanism.
Every outbound client in the app is bound to one fixed base address, and that address is checked against the list when the client is created. A client bound to https://data.sec.gov can only ever append a path to that base; it cannot be pointed elsewhere later. Ten clients exist: Yahoo four ways, SnapTrade, the license service, the release check, the updater twice, and EDGAR. Seven are wrapped by the allowlist itself, and two check their addresses against it before they are built.
One does neither, and you would find it, so here it is. The client that fetches quotes and price history comes from a third-party Rust library, and the app never asks the allowlist about it. That library's addresses are fixed in its source, and they are the three Yahoo addresses already on the list, so nothing reaches anywhere else today. But "on the list because the dependency happens to agree" is weaker than "checked", and a coming release adds that check.
Two smaller rules close the usual gaps. Redirects are refused, so a signed request can never be bounced from an allowed address to a different one. The minimum TLS version is 1.2. There is a debug-only function that can add an address for local testing; it is compiled out of release builds, and the tests assert that a URL cannot smuggle an allowed name into the user-info slot (https://www.pyx.finance@evil.example.com/ is refused).
Now the honest caveat. This is a code convention backed by tests, not an operating-system sandbox. A future mistake could create a client that skips the wrapper, and no amount of unit testing proves a negative about code that has not been written yet. That is exactly why the list is published and why the next section exists: the promise is falsifiable from outside the app, on your machine, without my help.
Check it yourself in ten minutes#
Three ways, cheapest first. Any one of them is enough.
1. Nothing to install: Terminal. Open Terminal while Pyx is running and paste:
lsof -i -P -n | grep -i pyx
Each line is one open connection. The right-hand column is the address Pyx is talking to, and every one should resolve to a name in the table above. For a live view that updates as you click around the app, use nettop -p Pyx, naming the process as it appears in Activity Monitor.
2. A free app. Little Snitch Mini shows a live list of every connection each app makes; monitoring is free, blocking is the paid part, and macOS 12 or later is required. LuLu from Objective-See is free, open source, and also blocks. Either one answers the question.
3. Little Snitch. The full product is paid, and its demo mode runs everything for three hours at a time and can be restarted as often as you like, which is more than this audit needs.
Whichever you pick, run the app through a session that touches every service:
- Install Pyx from the public download and go through onboarding.
- Import a CSV or OFX statement. This touches nothing on the internet except Yahoo, to name the securities in the file.
- Open Holdings, then open one company's research page. That is Yahoo and the SEC.
- Open a chart.
- Run Check for Updates from Settings, About. That is the website.
- If you subscribe, link a brokerage. That is SnapTrade and the license service.
Every row attributed to Pyx should be one of the nine.
You will also see rows that are not Pyx. When any signed app launches, macOS itself checks Apple's servers, usually ocsp.apple.com and, on first launch, api.apple-cloudkit.com, to confirm the developer's certificate and the notarization ticket. Those rows belong to system processes such as trustd and syspolicyd, not to the Pyx process, and they happen for every app on your Mac. A first-time Little Snitch user can easily mistake them for the app. They are Apple's traffic, not mine.
If you ever see anything else#
The list changes only with a release, a line in the changelog, an update to the table in the privacy policy, and an updated date on this post. Any address added for a new data source starts off and has its own switch. If you see an address that is not on the list and not one you turned on, email support@pyx.finance, and the finding goes in the changelog with your name if you want it there. No bounty program, no form. Just the commitment, in writing, on a page you can hold me to.
Pyx is a local-first portfolio app for the Mac that keeps your data in files you own. The privacy and security guide covers what the rest of the app does with your data once it is on disk.