# Nitter Cookie API vs OAuth API: Understanding the Authentication Variants

> Explore Nitter's Cookie API vs OAuth API authentication differences. Understand how Nitter handles browser-style tokens and cryptographically signed requests for API access.

- Repository: [Zed/nitter](https://github.com/zedeus/nitter)
- Tags: deep-dive
- Published: 2026-08-29

---

**Nitter supports two distinct authentication mechanisms—Cookie sessions that transmit browser-style auth tokens to x.com, and OAuth 1.0a sessions that cryptographically sign requests for api.x.com—with both variants handled by the `genHeaders` function in `src/apiutils.nim` based on the `SessionKind` enum.**

Nitter, the privacy-focused Twitter/X frontend maintained in the zedeus/nitter repository, provides dual authentication paths for accessing Twitter's private API. Understanding the difference between Nitter's Cookie API and OAuth API variants is critical for developers configuring instances or contributing to the codebase. While both methods ultimately invoke the same high-level API functions like `fetch`, they diverge significantly in credential storage, header construction, and endpoint targeting.

## Core Authentication Mechanisms

### Cookie-Based Sessions (SessionKind.cookie)

The **Cookie API** variant mimics browser authentication by transmitting session credentials directly to Twitter's web endpoints. In `src/types.nim` (lines 30-48), the cookie variant stores `authToken` and `ct0` values within the `Session` record.

When constructing requests, the `genHeaders` function in `src/apiutils.nim` (lines 94-101) adds a cookie header containing `auth_token` and `ct0` values. The function also injects the `x-twitter-auth-type: OAuth2Session` header and a CSRF token via `x-csrf-token` to satisfy Twitter's web client security requirements.

This variant targets `https://x.com/i/api/...` endpoints, as determined by the `toUrl` function's branch for `SessionKind.cookie` in `src/apiutils.nim` (lines 51-58).

### OAuth 1.0a Sessions (SessionKind.oauth)

The **OAuth API** variant implements the OAuth 1.0a protocol, generating cryptographically signed Authorization headers using consumer key/secret pairs combined with user-specific OAuth tokens and secrets. The `Session` record stores these as `oauthToken` and `oauthSecret` fields according to the type definition in `src/types.nim` (lines 42-45).

In the `genHeaders` function, the `SessionKind.oauth` branch calls `getOauthHeader` to produce the signature, injecting the result as an `authorization` header. This variant communicates with `https://api.x.com/...` endpoints, selected by the `toUrl` function when processing OAuth sessions.

## Implementation Architecture

The authentication abstraction centers on the **`SessionKind`** enum and the **`Session`** variant type defined in `src/types.nim`. The codebase remains agnostic to authentication method through unified wrappers:

- **`fetch`** and **`fetchRaw`**: High-level API functions that accept an `ApiReq` object and internally delegate to the appropriate authentication logic based on the session type.

The **`toUrl`** function handles endpoint selection logic, routing cookie sessions to the x.com domain while directing OAuth traffic to api.x.com. This separation ensures that each authentication variant communicates with its expected Twitter API surface.

## Practical Implementation Examples

### Configuring a Cookie-Based Session

To authenticate using browser-extracted cookies, populate the `Session` object with `kind: SessionKind.cookie` and provide the extracted `authToken` and `ct0` values:

```nim
import types, apiutils, api

let cookieReq = ApiReq(
  cookie: ApiUrl(
    endpoint: "1.1/statuses/user_timeline.json",
    params: @[("screen_name", "example")]
  ),
  oauth: ApiUrl(
    endpoint: "1.1/statuses/user_timeline.json",
    params: @[]
  )
)

var sess = Session(
  kind: SessionKind.cookie,
  authToken: "YOUR_AUTH_TOKEN",
  ct0: "YOUR_CT0"
)

let url = toUrl(cookieReq, sess.kind)

# Generates: https://x.com/i/api/1.1/statuses/user_timeline.json

let hdrs = await genHeaders(sess, url, skipTid = false)
let body = await fetch(cookieReq)
echo body

```

### Configuring an OAuth 1.0a Session

For OAuth authentication, initialize the session with consumer credentials and user tokens, allowing `getOauthHeader` to generate the cryptographic signature:

```nim
import types, apiutils, api

let oauthReq = ApiReq(
  oauth: ApiUrl(
    endpoint: "1.1/statuses/user_timeline.json",
    params: @[("screen_name", "example")]
  ),
  cookie: ApiUrl(
    endpoint: "1.1/statuses/user_timeline.json",
    params: @[]
  )
)

var sess = Session(
  kind: SessionKind.oauth,
  oauthToken: "USER_OAUTH_TOKEN",
  oauthSecret: "USER_OAUTH_SECRET"
)

let url = toUrl(oauthReq, sess.kind)

# Generates: https://api.x.com/1.1/statuses/user_timeline.json

let hdrs = await genHeaders(sess, url, skipTid = false)
let body = await fetch(oauthReq)
echo body

```

## Security and Rate Limiting Differences

Both authentication variants grant full account access if credentials are compromised, but they present different security surface areas. **Cookie sessions** require safeguarding `auth_token` and `ct0` values extracted from browser sessions, while **OAuth sessions** protect consumer secrets and user-specific OAuth tokens.

Rate limiting implementations vary slightly between variants. Cookie sessions can optionally bypass the GraphQL "Tid" header (using `authorization: bearerToken2`) when the `disableTid` flag is set, whereas OAuth sessions consistently include the standard `authorization: bearerToken` header except when specifically targeting legacy `/1.1/` endpoints.

## Summary

- **Cookie API**: Uses `auth_token` and `ct0` cookies with `x-twitter-auth-type: OAuth2Session` and `x-csrf-token` headers, targeting `https://x.com/i/api/...`, with implementation in `src/apiutils.nim` lines 94-101.
- **OAuth API**: Uses OAuth 1.0a signatures generated by `getOauthHeader`, targeting `https://api.x.com/...`, with credentials stored in `oauthToken` and `oauthSecret` fields per `src/types.nim` lines 42-45.
- **Unified Interface**: Both variants use the same `fetch` and `ApiReq` abstractions, switching behavior via the `SessionKind` enum.
- **Endpoint Separation**: The `toUrl` function in `src/apiutils.nim` (lines 51-58) routes cookie traffic to x.com and OAuth traffic to api.x.com based on session type.

## Frequently Asked Questions

### Which authentication method should I use for my Nitter instance?

Choose the **Cookie API** when you have valid browser session tokens (`auth_token` and `ct0`) extracted from an authenticated Twitter session, as this mimics the official web client. Select the **OAuth API** when you possess OAuth 1.0a consumer credentials and user tokens, which provide standardized API access without requiring active browser sessions.

### What files handle the authentication logic in Nitter?

The primary files are `src/types.nim` (defining the `Session` variant and `SessionKind` enum), `src/apiutils.nim` (implementing `genHeaders` and `toUrl` for header construction and endpoint selection), and `src/auth.nim` (managing the session pool and request routing).

### Can I switch between Cookie and OAuth authentication without changing the API code?

Yes. The high-level API functions like `fetch` remain agnostic to the authentication method. You only need to change the `Session` object's `kind` field and corresponding credentials; the internal logic in `genHeaders` automatically selects the appropriate header construction and endpoint URL via `toUrl`.

### How does Nitter handle rate limits differently for each authentication type?

Both variants respect Twitter's rate limits, but cookie sessions offer additional flexibility through the `disableTid` flag to bypass certain GraphQL headers. OAuth sessions maintain consistent authorization header patterns using `bearerToken` across all requests unless specifically targeting legacy 1.1 endpoints.