Privacy
No accounts, no profiles, very little kept.
x.md has no sign-in and no user accounts, so there is nothing to build a profile from. This page describes what actually happens to a request, taken from the code in the public repository.
No accounts, no credentials
There is no registration, login, password, or session. x.md never asks for your X credentials, cannot act on an X account, and has no way to associate a request with a person. Private API keys exist for a small number of callers who need a larger search allowance; they are handed out privately, only a SHA-256 hash of the secret is stored, and they carry a label and a limit — not a person.
What a request necessarily involves
Like any website, your request reaches Vercel’s edge with an IP address and ordinary HTTP headers, and Vercel operates the hosting and CDN under its own terms. Inside the application, the client IP address is read from the standard proxy headers for two purposes. For rate limiting it becomes part of a counter key in a key/value store, the counter holds only a number, and the key expires automatically — roughly two minutes for the per-minute search gate and about half an hour for the fifteen-minute search budget. No URL, query, response, or header is written beside it. Rate limits protect scarce upstream capacity, above all for live search. For analytics the IP is only ever used as the input to a daily caller hash, described below, and is never stored.
Caching
Conversion and browse results are cached under a key derived from the request parameters, in the serverless instance’s memory and at Vercel’s CDN, for an hour by default for posts and from ten minutes (searches) to six hours (follower lists) for browse results. What is cached is public X content, not anything about you, and ?nocache=true bypasses it. Responses to requests that carry an API key are marked private, no-store so they can never be served from a shared cache to somebody else.
Analytics
Two optional, metadata-only instrumentations run on the production deployment when they are configured. Neither one is required for the service to work, and both are absent from local and preview builds.
- Server-side request counting. One event per completed production function response, carrying only the route name, HTTP method, status code, duration in milliseconds, cache outcome, whether the caller used a key, and the environment. Request-counting events exclude the request URL, query, headers, body, and error text. Person profiles and GeoIP enrichment are disabled and the IP field is explicitly sent as null. Anonymous callers all share one fixed identifier, and each event carries a caller ID: a keyed hash of the IP under a secret salt that changes every UTC day, so callers can be counted per day but not identified, reversed, or linked from one day to the next. API-key callers get an HMAC of the internal key ID, never the key itself. Unexpected errors that escape API handlers are reported separately with their type, message, and stack frames. URL query strings and fragments are stripped, source context is removed, and request data and caller identities are not attached. Error events share a fixed server identifier, with person profiles and GeoIP enrichment disabled.
- Homepage and docs analytics. The homepage and the documentation pages under /docs may load PostHog to count page views and page leaves, plus two homepage interactions: requesting a conversion and copying the skill install command. Properties are reduced to an allowlist of browser, device, viewport, and session fields, plus where the visit came from: the referring site’s origin (never its path or query) and the standard utm_source, utm_medium, utm_campaign, utm_content, and utm_term campaign tags. The reported URL is the page’s origin and path; every other query parameter and the fragment are removed. Uncaught JavaScript errors are reported too, reduced to the error type, message, and stack frames, with query strings and fragments stripped from any URL inside them. Autocapture, session recording, heatmaps, surveys, and person profiles are all switched off. Vercel Web Analytics is also injected on the homepage and the documentation pages.
Cookies and local storage
The API sets no cookies at all. In the browser, x.md stores your light/dark theme choice in localStorage under blume-theme, and the analytics library, when it runs, keeps its own anonymous identifier there. One optional cookie exists, __Host-xmd_actor: it holds an anonymous UUID, is set only in builds where the operator has enabled the archive actor bridge, and is scoped Secure; SameSite=Lax; Path=/ with a 30-day lifetime. Opting out writes a second cookie, __Host-xmd_archive_optout=1, which the server also honours.
The optional public-result archive
The repository contains an opt-in capture path that sends the structured public results of successful GET responses — post fields, public author fields, media metadata — to PostHog for later export. It is disabled by default and requires an operator to set an explicit environment flag plus a separate server-only secret; it never runs in local or preview builds. Its payloads use strict field allowlists that exclude rendered response bodies, incoming URLs and search queries, request headers, IP addresses, credentials, and cursors, and protected authors are excluded entirely.
Your controls
- Send DNT: 1, Sec-GPC: 1, or X-Xmd-Archive-Opt-Out: 1 with a request, or set the __Host-xmd_archive_optout=1 cookie: archive capture is skipped and the homepage and docs analytics do not initialise.
- Use ?nocache=true to bypass the application cache for a request.
- Block the third-party requests listed below, or run the service yourself — a self-hosted deployment with no analytics variables configured sends nothing anywhere unless an agent calls the MCP submit_feedback tool.
Third parties
Serving a request involves Vercel (hosting and CDN) and the upstream public X endpoints and FxTwitter that supply the content. When analytics are configured, events go to a PostHog instance. Loading the landing page in a browser additionally fetches a web font from Fontshare and a Product Hunt badge image; both are ordinary third-party requests made by your browser and can be blocked without affecting the API. When an agent calls the MCP submit_feedback tool, the message it writes, with any title, kind, sentiment, and context URL, goes to Notra, which hosts the x.md feedback inbox; nothing else from the request is attached.
Changes
This page describes the behaviour of the code in the public repository, which is the authoritative record — every claim above can be checked against the source. Questions and corrections go to contact. Last reviewed .