# How Nitter Achieves User Privacy: Server-Side Architecture and Zero-Client-Tracking Design

> Discover how Nitter ensures user privacy. Learn about its server-side architecture and zero-client-tracking design that shields your IP and browser from Twitter.

- Repository: [Zed/nitter](https://github.com/zedeus/nitter)
- Tags: architecture
- Published: 2026-09-04

---

**Nitter achieves user privacy by proxying all Twitter API requests through its server, serving static HTML without JavaScript, and storing only non-identifying UI preferences in cookies, ensuring your IP address and browser fingerprint never reach Twitter.**

Nitter, the open-source alternative Twitter front-end maintained by `zedeus/nitter`, is engineered specifically to eliminate the surveillance mechanisms inherent in standard Twitter browsing. Unlike conventional clients that expose your IP address and execute tracking scripts in your browser, Nitter implements a privacy-first architecture based on server-side network isolation and stateless operation. This design ensures that your identity remains completely isolated from Twitter's infrastructure while maintaining full access to public timelines and content.

## Server-Side Network Isolation

Nitter's core privacy guarantee stems from **network-level isolation**. All communication with Twitter's unofficial API occurs exclusively on the server side; your browser never initiates a direct connection to Twitter's domains.

In `src/api.nim`, the backend constructs and executes every HTTP request through functions like `apiReq`, `fetch`, and `fetchRaw`. The server retrieves data from Twitter's GraphQL endpoints, parses the JSON responses, and renders pure HTML before sending it to your browser. This proxy architecture means Twitter only sees the IP address of the Nitter instance, never your personal IP address or browser fingerprint.

### The API Proxy Implementation

The `getGraphUserTweets` procedure in `src/api.nim` demonstrates how timeline data is fetched server-side without exposing request details to the client:

```nim

# src/api.nim – fetch a user’s tweets via the backend GraphQL endpoint

proc getGraphUserTweets*(id: string; kind: TimelineKind; after=""): Future[Profile] {.async.} =
  if id.len == 0: return
  let cursor = cursorParam(after)
  let url = case kind
    of TimelineKind.tweets: userTweetsUrl(id, cursor)
    of TimelineKind.replies: userTweetsAndRepliesUrl(id, cursor)
    of TimelineKind.media: mediaUrl(id, cursor)
    of TimelineKind.articles: userArticlesUrl(id, cursor)
  let js = await fetch(url)                     # ← server‑side HTTP call

  result = parseGraphTimeline(js, after)        # ← parse JSON, render HTML

```

The client receives only the rendered HTML timeline. The underlying Twitter URL, authentication headers, and response metadata remain entirely within the server's memory space.

## Zero JavaScript and No Client-Side Tracking

Nitter serves **static HTML and CSS** with **no JavaScript** execution required for core functionality (excluding optional Karax UI for the preferences panel). As stated in the repository's [`README.md`](https://github.com/zedeus/nitter/blob/main/README.md), the project explicitly guarantees "No JavaScript or ads" as a fundamental feature.

Without JavaScript execution, there is no attack surface for browser fingerprinting, canvas tracking, or third-party analytics scripts. Your browser renders pure markup and stylesheets, eliminating the behavioral tracking mechanisms that standard Twitter employs through its JavaScript bundles.

## Stateless Preference Storage Without Personal Data

When you customize Nitter's interface—selecting themes, video playback options, or display modes—these settings are stored in a browser cookie named `prefs` that contains **only** the UI configuration values. No identifying information such as Twitter usernames, OAuth tokens, or session identifiers ever reaches the client storage.

The preferences system is implemented in `src/views/preferences.nim` and `src/prefs_impl.nim`. The cookie stores a simple JSON object (e.g., `{"theme":"dark","hlsPlayback":"on"}`) and explicitly excludes any personal data.

### Cookie-Based Settings Implementation

The preferences interface renders a standard HTML form that submits to `/saveprefs`:

```nim

# src/views/preferences.nim – HTML form that writes a cookie called “prefs”

buildHtml(tdiv(class="overlay-panel")):
  fieldset(class="preferences"):
    form(method="post", action="/saveprefs", autocomplete="off"):
      renderPrefs()               # renders checkboxes, selects, etc.

      button(type="submit"): text "Save preferences"

```

Upon submission, the server serializes your choices into the `prefs` cookie. Because this cookie contains exclusively UI state and no tracking IDs or authentication tokens, it cannot be used to correlate your browsing sessions across different Nitter instances or link your activity to a Twitter identity.

## Backend-Only Session Management

When Nitter requires authentication to query Twitter's API, it manages session cookies and OAuth tokens strictly within the backend. Files like `src/auth.nim` and `src/apiutils.nim` construct `ApiReq` objects that maintain separate `cookie` and `oauth` endpoints entirely on the server.

These authentication credentials are **never exposed to the frontend**. The server strips all user-identifying data from responses before transmitting HTML to your browser. This ensures that even if Nitter must authenticate with Twitter to fetch content, those credentials remain isolated from your client environment.

## Summary

Nitter's privacy architecture relies on three coordinated technical strategies:

- **Server-side proxying**: All Twitter API requests execute in `src/api.nim`, ensuring your IP address and request metadata never reach Twitter's infrastructure.
- **Static content delivery**: The absence of JavaScript eliminates browser fingerprinting, analytics tracking, and client-side data collection.
- **Minimal cookie storage**: Only non-identifying UI preferences are stored locally in the `prefs` cookie, with no OAuth tokens, session IDs, or personal data ever written to client storage.

## Frequently Asked Questions

### Does Nitter expose my IP address to Twitter?

No. Because all requests to Twitter's API are proxied through the Nitter server using the `fetch` and `apiReq` procedures in `src/api.nim`, Twitter only sees the IP address of the Nitter instance itself. Your personal IP address remains hidden from Twitter's logs and tracking systems.

### Is JavaScript required to use Nitter?

No. Nitter serves static HTML and CSS by default. The repository's [`README.md`](https://github.com/zedeus/nitter/blob/main/README.md) explicitly lists "No JavaScript" as a core feature. An optional JavaScript-based UI exists only for the preferences panel using the Karax framework, but all content browsing functions work entirely without script execution.

### What personal data does Nitter store?

Nitter stores no personal data on its servers. The only persistent data stored on your device is the `prefs` cookie, which contains only UI configuration options like theme selection and video playback preferences. As implemented in `src/prefs_impl.nim`, this cookie explicitly excludes usernames, passwords, OAuth tokens, or any identifying information.

### Can Nitter access my private Twitter account or DMs?

No. Nitter operates without user accounts and cannot authenticate as you. The system uses its own backend session tokens (managed in `src/auth.nim`) to fetch public Twitter content only. There is no mechanism for Nitter to access private messages, protected tweets, or account-specific data requiring your personal Twitter credentials.