# How wechat-article-exporter Handles WeChat API Session Expiration (ret code 200003)

> Learn how wechat-article-exporter solves WeChat API session expiration errors ret code 200003 by automatically re-logging in and retrying failed requests.

- Repository: [公众号文章工具箱/wechat-article-exporter](https://github.com/wechat-article/wechat-article-exporter)
- Tags: internals
- Published: 2026-05-26

---

**When the WeChat MP backend returns ret code 200003, the exporter automatically invalidates the stored authentication cookie, triggers a re-login flow via QR code, and retries the failed request once the session is restored.**

The `wechat-article-exporter` project provides a robust solution for exporting WeChat articles by interfacing with the official WeChat MP (Weixin Official Accounts Platform) backend. When your **WeChat API session expires**—signaled by the specific error code **ret = 200003**—the application implements a seamless recovery mechanism that clears stale credentials and guides you through re-authentication without losing export progress.

## Understanding the WeChat API Session Expiration Signal

WeChat MP endpoints return a JSON payload containing a `base_resp` object with a `ret` status code. While `ret: 0` indicates success, **ret code 200003** specifically means "session expired" or "login status expired," requiring immediate re-authentication.

### The WeChat MP Response Structure

When the session cookie (containing the `token` obtained from QR-code login) becomes invalid, the API responds with:

```json
{
  "base_resp": { 
    "ret": 200003, 
    "err_msg": "session expired" 
  }
}

```

According to the source code analysis, the exporter treats this **ret = 200003** as a definitive session-expiration signal that triggers the credential refresh workflow.

## Detecting ret code 200003 in the Proxy Layer

All frontend requests route through the central proxy utility located at [`server/utils/proxy-request.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/utils/proxy-request.ts). The `proxyMpRequest()` function forwards every request to the WeChat MP backend and inspects the response for session expiration.

After receiving the response via `fetch()`, the code parses the JSON and checks the `base_resp.ret` value:

```ts
// server/utils/proxy-request.ts
const json = await finalResponse.json();
if (json.base_resp?.ret === 200003) {
  // Forward the error to the caller with HTTP 401
  return new Response(JSON.stringify(json), { status: 401 });
}
return json;   // Normal path for ret === 0

```

This detection ensures that any **WeChat API session expiration** is immediately surfaced to the frontend with a standard HTTP 401 status code, separating transport errors from authentication failures.

## Recovering from Session Expiration

When the proxy detects ret = 200003, the frontend composable [`useLoginCheck.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/useLoginCheck.ts) intercepts the error and initiates a three-phase recovery process.

### Clearing Stale Authentication Data

The `useLoginCheck` composable performs critical cleanup operations when it encounters the 200003 error:

1. **Removes the server-side session**: Calls the `/api/web/login/logout` endpoint to purge the `auth-key` from KV storage via `CookieStore.setCookie` and `CookieStore.updateCookie` methods defined in [`server/utils/CookieStore.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/utils/CookieStore.ts)
2. **Emits logout event**: Dispatches a `logout` event through `useAccountEventBus` to notify all components of the authentication state change
3. **Forces UI transition**: Redirects the user to the login page to initiate fresh QR-code authentication

```ts
// composables/useLoginCheck.ts
export function useLoginCheck() {
  const { callMpApi } = useApis();
  const accountBus = useAccountEventBus();

  async function guardedCall(options) {
    const resp = await callMpApi(options);
    if (resp.base_resp?.ret === 200003) {
      // Session expired → clear auth-key and ask user to log in again
      await fetch('/api/web/login/logout'); // removes KV entry
      accountBus.emit('logout');
      throw new Error('WeChat session expired – please log in again.');
    }
    return resp;
  }

  return { guardedCall };
}

```

### The Logout API Endpoint

The [`server/api/web/login/logout.get.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/api/web/login/logout.get.ts) endpoint handles the server-side removal of stored session data from the KV store. This ensures the stale `auth-key` cannot be reused by subsequent requests, preventing infinite loops of invalid authentication attempts.

## Automatic Retry After Re-Authentication

Once the user completes the QR-code login flow again and obtains fresh cookies, the [`composables/useDownloader.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/composables/useDownloader.ts) logic automatically retries the original failed request. This happens transparently without requiring manual restart of the export process, ensuring that **ret code 200003** interruptions do not result in data loss or failed exports.

The retry mechanism works by wrapping API calls with the `guardedCall` function from `useLoginCheck`, catching session errors, waiting for the re-authentication event, and then re-issuing the request with the new valid cookies.

## Summary

- **Detection**: The proxy layer in [`server/utils/proxy-request.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/utils/proxy-request.ts) identifies **ret code 200003** by checking `json.base_resp?.ret === 200003` after each MP API call
- **Signaling**: The proxy returns HTTP 401 to clearly signal **WeChat API session expiration** to the frontend
- **Cleanup**: [`composables/useLoginCheck.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/composables/useLoginCheck.ts) clears the KV-stored `auth-key` via [`server/utils/CookieStore.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/utils/CookieStore.ts) and emits logout events through `useAccountEventBus`
- **Server-side cleanup**: [`server/api/web/login/logout.get.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/api/web/login/logout.get.ts) removes the stale session from storage
- **Resilience**: [`composables/useDownloader.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/composables/useDownloader.ts) provides automatic retry logic after successful re-login, maintaining export continuity

## Frequently Asked Questions

### What does WeChat API ret code 200003 mean?

**Ret code 200003** indicates that the session cookie containing your WeChat MP authentication token has expired or become invalid. The WeChat backend returns this code in the `base_resp.ret` field when it can no longer associate your request with a valid logged-in user session, requiring you to re-authenticate via QR code.

### Which file handles the detection of session expiration?

The [`server/utils/proxy-request.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/utils/proxy-request.ts) file contains the `proxyMpRequest()` function that inspects every WeChat MP response. After parsing the JSON with `finalResponse.json()`, it specifically checks for `json.base_resp?.ret === 200003` and returns an HTTP 401 response to signal the frontend that re-authentication is required.

### How does wechat-article-exporter store session credentials?

The application uses a **KV-backed CookieStore** implemented in [`server/utils/CookieStore.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/server/utils/CookieStore.ts). The `auth-key` and associated WeChat cookies are persisted in KV storage with methods like `CookieStore.setCookie()` and `CookieStore.updateCookie()`, allowing the server to maintain your session across requests until a **ret code 200003** error triggers cleanup.

### Will my download progress be lost when re-authenticating?

No. The [`composables/useDownloader.ts`](https://github.com/wechat-article/wechat-article-exporter/blob/main/composables/useDownloader.ts) composable implements automatic retry logic that re-issues failed requests once the `useLoginCheck` composable confirms a fresh session is established. Since the download state is maintained independently of the authentication layer, the export resumes from where it left off after you complete the QR-code login flow.