# How Nitter Fetches a User Profile by Username: The fetchProfile Function Explained

> Discover how Nitter uses the fetchProfile function in timeline.nim to retrieve user profiles by username. Understand the process and data returned by this essential Nitter routine.

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

---

**Nitter retrieves a user’s profile through the `fetchProfile` routine defined in `src/routes/timeline.nim`, which accepts a `Query` object containing the target username and returns a fully populated `Profile` structure with timeline data.**

Nitter is an open-source alternative Twitter frontend that aggregates social media content without requiring JavaScript or user accounts. When you navigate to a user timeline such as `/<username>/`, the application invokes a specific asynchronous routine to resolve identifiers and render profile information. According to the zedeus/nitter source code, the `fetchProfile` function serves as the central mechanism for retrieving user metadata and associated tweets by username.

## The fetchProfile Function Architecture

Located at line 49 of `src/routes/timeline.nim`, `fetchProfile` is an asynchronous procedure that orchestrates multiple data sources to construct a complete user profile. The function signature accepts an `after` parameter (used for pagination cursors) and a `Query` object whose `fromUser` field contains the requested username.

### Step 1: Username Extraction and ID Resolution

The function extracts the target username from the query structure:

```nim
name = query.fromUser[0]

```

It then resolves this to a numeric identifier through `getUserId(name)`. If `getUserId` returns an empty string, `fetchProfile` generates a minimal `Profile` containing only the username. If the ID equals `"suspended"`, the function returns a `Profile` marked with the suspended flag, which triggers an error page in the calling router.

### Step 2: Timeline Selection and GraphQL Queries

Based on the `query.kind` enum—which may specify `posts`, `replies`, `media`, or `articles`—the function selects the appropriate GraphQL helper from `src/api.nim`:

- **`getGraphUserTweets`** for standard user posts
- **`getGraphTweetSearch`** for replies and advanced search filters

These helpers fetch the actual tweet content, media attachments, and conversation threads from Twitter's internal API endpoints.

### Step 3: Auxiliary Data Aggregation

Before returning the result, `fetchProfile` enriches the profile with optional cached data:

- **Photo rail**: A cached strip of visual media
- **User object**: Full metadata retrieved via `getCachedUser`
- **Account information**: Additional profile context and statistics

The final `Profile` object contains the `User` structure, populated tweets, and the original `Query` attached for template rendering.

## Code Implementation Examples

### Router Integration

When the `showTimeline` route handler processes a request, it calls `fetchProfile` and validates the account status:

```nim

# Inside src/routes/timeline.nim

var profile = await fetchProfile(after, query)
if profile.user.suspended:
    return showError(getSuspended(profile.user.username), cfg)

let html = renderProfile(profile, prefs, getPath())
result = renderMain(html, request, cfg, prefs, pageTitle(profile.user.username))

```

### Direct Module Usage

You can import and invoke the function directly from other Nim modules:

```nim
import src/routes/timeline

# Assume query is instantiated with fromUser = @["someuser"]

let prof = await fetchProfile("", query)
echo "User ID: ", prof.user.id
echo "Tweet count: ", prof.tweets.content.len

```

### Lightweight User Fetching

For scenarios requiring only user metadata without timeline data, access the caching layer directly:

```nim
let user = await getCachedUser("someuser")
echo "Full name: ", user.fullname
echo "Profile pic: ", user.getUserPic("_400x400")

```

## Core Source Files

The profile fetching pipeline spans several key files in the zedeus/nitter repository:

- **`src/routes/timeline.nim`**: Defines `fetchProfile` and handles routing for timelines, RSS feeds, and infinite scroll endpoints.
- **`src/api.nim`**: Implements GraphQL helpers including `getGraphUserTweets` and `getGraphTweetSearch` for Twitter API communication.
- **`src/parser.nim`**: Parses raw Twitter JSON responses into `User` and `Profile` Nim objects.
- **`src/http_pool.nim`**: Manages the HTTP client pool used for all external API requests.
- **`src/views/profile.nim`**: Renders the HTML representation of the fetched `Profile` structure.

## Summary

- **`fetchProfile`** in `src/routes/timeline.nim` is the primary function for fetching user profiles by username in Nitter.
- The function resolves usernames to user IDs via `getUserId` and handles suspended account detection before querying timelines.
- Timeline content retrieval varies by type (posts, replies, media, articles) using specialized GraphQL endpoints from `src/api.nim`.
- The function returns a fully populated `Profile` object containing both user metadata and tweet content ready for rendering.
- **`getCachedUser`** provides a lightweight alternative for retrieving user metadata without invoking full timeline fetching.

## Frequently Asked Questions

### How does Nitter resolve a username to a user ID?

Nitter calls the `getUserId` function with the extracted username from `query.fromUser[0]`. This function performs an asynchronous lookup against Twitter's identifier system. If the username cannot be resolved, `fetchProfile` returns a minimal profile structure containing only the username string, allowing the application to handle missing accounts gracefully.

### What happens when a user account is suspended?

If `getUserId` returns the string `"suspended"`, `fetchProfile` immediately constructs a `Profile` with the suspended flag set to true. The calling router then renders an error page using `showError` and `getSuspended`, preventing any further API calls or data processing for that account.

### Can I fetch a user profile without retrieving the full timeline?

Yes. For metadata-only retrieval, use `getCachedUser(username)` directly from the caching layer. This returns a `User` object containing the full name, profile picture, and bio without invoking the GraphQL timeline queries or pagination logic required by `fetchProfile`.

### Which GraphQL endpoints does fetchProfile use?

The function selects endpoints based on `query.kind`. For standard posts, it uses `getGraphUserTweets`. For replies and search-based queries, it utilizes `getGraphTweetSearch`. These functions are implemented in `src/api.nim` and interface with Twitter's internal GraphQL API to retrieve tweet data, media entities, and conversation threads.