# How User Login Status Is Managed and Checked in Xiaohongshu-MCP

> Learn how Xiaohongshu-MCP manages user login status by checking DOM elements and using persistent session cookies for automatic re-authentication. Explore the technical details.

- Repository: [zy/xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp)
- Tags: internals
- Published: 2026-03-09

---

**Xiaohongshu-MCP determines user login status by detecting a specific DOM element on the Xiaohongshu explore page while persisting session cookies to disk for automatic re-authentication across browser instances.**

The xpzouying/xiaohongshu-mcp project automates interactions with Xiaohongshu (Little Red Book) through a Model Context Protocol implementation. Understanding how user login status is managed and checked is essential for maintaining persistent sessions across API calls without requiring repeated authentication.

## Runtime Login Detection via DOM Inspection

The core mechanism for verifying authentication relies on **browser automation** using the Rod library to inspect the Xiaohongshu web interface.

### Navigating to the Explore Page

When checking authentication state, the system navigates to `https://www.xiaohongshu.com/explore` and waits for the page to fully load. This URL serves as the entry point for detecting user-specific UI elements that only appear post-authentication.

### The Login Indicator Selector

The actual detection occurs by querying for the CSS selector `.main-container .user .link-wrapper .channel`. This element represents the user avatar and name block in the Xiaohongshu interface, which is only rendered after a successful login.

In [`xiaohongshu/login.go`](https://github.com/xpzouying/xiaohongshu-mcp/blob/main/xiaohongshu/login.go), the `CheckLoginStatus` method implements this logic:

```go
// xiaohongshu/login.go – CheckLoginStatus
func (a *LoginAction) CheckLoginStatus(ctx context.Context) (bool, error) {
    pp := a.page.Context(ctx)
    pp.MustNavigate("https://www.xiaohongshu.com/explore").MustWaitLoad()
    time.Sleep(1 * time.Second)

    exists, _, err := pp.Has(`.main-container .user .link-wrapper .channel`) // detection
    if err != nil {
        return false, errors.Wrap(err, "check login status failed")
    }
    if !exists {
        return false, errors.Wrap(err, "login status element not found")
    }
    return true, nil
}

```

## Service Layer Abstraction

The service layer in [`service.go`](https://github.com/xpzouying/xiaohongshu-mcp/blob/main/service.go) wraps the login action to provide a clean API response. It initializes a new browser instance (which automatically loads any persisted cookies), creates a page, and delegates to the login action:

```go
// service.go – CheckLoginStatus
func (s *XiaohongshuService) CheckLoginStatus(ctx context.Context) (*LoginStatusResponse, error) {
    b := newBrowser()
    defer b.Close()
    page := b.NewPage()
    defer page.Close()

    loginAction := xiaohongshu.NewLogin(page)
    isLoggedIn, err := loginAction.CheckLoginStatus(ctx) // invokes the DOM check
    // ...
    response := &LoginStatusResponse{IsLoggedIn: isLoggedIn, Username: configs.Username}
    return response, nil
}

```

## QR Code Authentication and Session Establishment

When `CheckLoginStatus` returns false, the system initiates a **QR code login flow** that bridges the gap between manual user authentication and automated session persistence.

### Generating the Login QR Code

The `FetchQrcodeImage` method (invoked via `GetLoginQrcode` in the service layer) generates a QR code image for the user to scan with the Xiaohongshu mobile app.

### Polling for Authentication

After presenting the QR code, the system enters a polling loop via `WaitForLogin`, which checks for the same DOM selector every 500 milliseconds:

```go
// xiaohongshu/login.go – WaitForLogin (polls the same selector)
func (a *LoginAction) WaitForLogin(ctx context.Context) bool {
    pp := a.page.Context(ctx)
    ticker := time.NewTicker(500 * time.Millisecond)
    // ...
    for {
        select {
        case <-ticker.C:
            el, err := pp.Element(".main-container .user .link-wrapper .channel")
            if err == nil && el != nil {
                return true // login succeeded
            }
        }
    }
}

```

### Background Login Monitoring

The service layer launches this polling mechanism in a **background goroutine** that waits for successful authentication and immediately persists the session:

```go
// service.go – GetLoginQrcode
loginAction := xiaohongshu.NewLogin(page)
img, loggedIn, err := loginAction.FetchQrcodeImage(ctx)
// ...
if !loggedIn {
    go func() {
        ctxTimeout, cancel := context.WithTimeout(context.Background(), timeout)
        defer cancel()
        if loginAction.WaitForLogin(ctxTimeout) {
            // Persist cookies for later sessions
            _ = saveCookies(page)
        }
    }()
}

```

## Persistent Session Management

To avoid requiring QR code scanning on every request, xiaohongshu-mcp implements **cookie-based session persistence** that bridges browser instances.

### Saving Cookies to Disk

When `WaitForLogin` detects a successful authentication, the `saveCookies` helper serializes the browser's cookies to JSON and writes them to a local file:

```go
func saveCookies(page *rod.Page) error {
    cks, err := page.Browser().GetCookies()
    // ...
    data, err := json.Marshal(cks)
    // ...
    cookieLoader := cookies.NewLoadCookie(cookies.GetCookiesFilePath())
    return cookieLoader.SaveCookies(data)
}

```

### Loading Cookies on Browser Startup

Future invocations automatically reuse these cookies because the `newBrowser()` constructor (implemented in the browser package) loads the persisted cookies from the `cookies/` directory when initializing the Rod browser instance. This allows `CheckLoginStatus` to return true immediately if the cookies are still valid, bypassing the QR code flow.

### Invalidating Sessions

A dedicated API endpoint (`DELETE /login/cookies`) exposes the `DeleteCookies` method, which removes the persisted cookie file and forces a fresh authentication on the next request:

```go
func (s *XiaohongshuService) DeleteCookies(ctx context.Context) error {
    cookiePath := cookies.GetCookiesFilePath()
    cookieLoader := cookies.NewLoadCookie(cookiePath)
    return cookieLoader.DeleteCookies()
}

```

## Summary

- **DOM-based detection**: Login status is determined by checking for the `.main-container .user .link-wrapper .channel` selector on the Xiaohongshu explore page, which only appears after successful authentication.
- **QR code workflow**: Unauthenticated sessions trigger a QR code generation flow with a background goroutine that polls every 500 milliseconds for the login indicator.
- **Cookie persistence**: Successful authentications trigger `saveCookies` to serialize browser cookies to disk, while `newBrowser()` automatically loads these cookies to maintain sessions across API calls.
- **Session invalidation**: The `DeleteCookies` endpoint removes the stored cookie file, forcing a fresh QR code login on the next status check.

## Frequently Asked Questions

### How does xiaohongshu-mcp check if a user is logged in?

The system navigates to `https://www.xiaohongshu.com/explore` and checks for the presence of the CSS selector `.main-container .user .link-wrapper .channel` using the Rod browser automation library. If this element exists, the `CheckLoginStatus` function returns `true`, indicating an active session.

### Where are session cookies stored in xiaohongshu-mcp?

Session cookies are persisted to a local file within the `cookies/` directory, with the specific path determined by `cookies.GetCookiesFilePath()`. The `saveCookies` function in [`service.go`](https://github.com/xpzouying/xiaohongshu-mcp/blob/main/service.go) handles the JSON serialization and storage, while the browser package handles automatic loading on startup.

### What triggers the background login monitoring process?

When `GetLoginQrcode` detects that the user is not already logged in (via the `loggedIn` boolean from `FetchQrcodeImage`), it launches a background goroutine that calls `WaitForLogin`. This function polls every 500 milliseconds for the login indicator element, and upon detection, triggers `saveCookies` to persist the session.

### How can I force a new login in xiaohongshu-mcp?

To force re-authentication, call the `DELETE /login/cookies` endpoint or invoke the `DeleteCookies` method directly. This removes the persisted cookie file from disk, causing the next `CheckLoginStatus` call to return `false` and trigger a new QR code login flow.