# How Clash Nyanpasu Establishes and Uses the Clash WebSocket Connection for Real-Time Data

> Discover how Clash Nyanpasu establishes its Clash WebSocket connection using authenticated REST API calls and ws URLs to stream real-time data like connections logs and memory usage.

- Repository: [Nyanpasu/clash-nyanpasu](https://github.com/libnyanpasu/clash-nyanpasu)
- Tags: deep-dive
- Published: 2026-03-06

---

**Clash Nyanpasu establishes authenticated WebSocket connections to the Clash core by first retrieving server credentials via the REST API, then constructing secure ws:// URLs with encoded tokens to stream connections, logs, traffic, and memory data in real time.**

The libnyanpasu/clash-nyanpasu frontend implements a React-based architecture that communicates with the Clash proxy core through persistent WebSocket connections. This design enables the dashboard to display live connection states, bandwidth metrics, and system logs without the overhead of polling, utilizing hooks from the `frontend/interface/src/ipc/` directory to manage connection lifecycles.

## How the WebSocket Connection is Established

### Retrieving Core Credentials via useClashInfo

Before opening any WebSocket connection, the frontend must obtain the Clash core's server address and authentication token. According to the source code in [`frontend/interface/src/ipc/use-clash-info.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-info.ts), the `useClashInfo` hook uses **SWR** to fetch this data from the local REST endpoint:

```typescript
import useSWR from 'swr'
import { fetcher } from '../../utils'

export const useClashInfo = () => {
  const { data, error, mutate } = useSWR('/api/clash/info', fetcher)
  return {
    data,
    error,
    mutate,
  }
}

```

This returns an `info` object containing `server` (hostname:port) and `secret` (authentication token) required for subsequent WebSocket authentication.

### Building Authenticated WebSocket URLs

Located in [`frontend/interface/src/ipc/use-clash-web-socket.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-web-socket.ts) (lines 8-14), the `useClashWebSocket` hook constructs the base URL and authentication parameters using React's `useMemo` to prevent unnecessary recalculations:

```typescript
const wsBaseUrl = useMemo(() => `ws://${info?.server}`, [info?.server])

const tokenParams = useMemo(
  () => `token=${encodeURIComponent(info?.secret || '')}`,
  [info?.secret],
)

```

The token is URL-encoded and forced into the query string because the Clash core rejects WebSocket connections that lack a valid `token` parameter.

### Resolving Endpoint URLs for Data Streams

As implemented in lines 16-31 of the same file, a `resolveUrl` helper composes the final WebSocket endpoints for each data stream:

```typescript
const resolveUrl = (path: string) => `${wsBaseUrl}/${path}?${tokenParams}`

```

Four distinct endpoints are resolved for real-time data: `connections`, `logs`, `traffic`, and `memory`. These URLs are memoized in a `urls` object and only recomputed when the `info` object changes, ensuring stable references across React renders.

## Real-Time Data Streams and React Hooks

### Creating WebSocket Connections with AHooks

The `useClashWebSocket` hook leverages **AHooks**' `useWebSocket` utility to establish the actual socket connections. As shown in lines 34-40 of [`frontend/interface/src/ipc/use-clash-web-socket.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-web-socket.ts), empty strings are passed as URLs while credentials are loading, keeping the hooks idle until authentication data is available:

```typescript
const connectionsWS = useWebSocket(urls?.connections ?? '')
const logsWS        = useWebSocket(urls?.logs ?? '')
const trafficWS     = useWebSocket(urls?.traffic ?? '')
const memoryWS      = useWebSocket(urls?.memory ?? '')

```

Each returned object contains the WebSocket's `readyState`, `message` (latest data payload), `sendMessage` method, and connection controls. The hook aggregates these into a single return object (lines 42-48):

```typescript
return { connectionsWS, logsWS, trafficWS, memoryWS }

```

### Consuming Live Data in Components

UI components import `useClashWebSocket` and subscribe to specific streams through the returned socket objects. For example, to display live connection lists:

```tsx
import { useClashWebSocket } from '@/frontend/interface/src/ipc/use-clash-web-socket'

export const ConnectionList = () => {
  const { connectionsWS } = useClashWebSocket()

  const connections = useMemo(() => {
    try {
      return connectionsWS?.message ? JSON.parse(connectionsWS.message) : []
    } catch {
      return []
    }
  }, [connectionsWS?.message])

  return (
    <ul>
      {connections.map((c: any) => (
        <li key={c.id}>
          {c.name} – {c.status}
        </li>
      ))}
    </ul>
  )
}

```

For real-time traffic visualization:

```tsx
import { useClashWebSocket } from '@/frontend/interface/src/ipc/use-clash-web-socket'
import { Line } from 'react-chartjs-2'

export const TrafficChart = () => {
  const { trafficWS } = useClashWebSocket()
  const [dataPoints, setDataPoints] = useState<number[]>([])

  useEffect(() => {
    if (!trafficWS?.message) return
    const { upload, download } = JSON.parse(trafficWS.message)
    setDataPoints((prev) => [...prev.slice(-19), upload + download])
  }, [trafficWS?.message])

  const chartData = {
    labels: dataPoints.map((_, i) => i),
    datasets: [{ 
      label: 'Traffic (bytes)', 
      data: dataPoints, 
      borderColor: '#42b983' 
    }],
  }

  return <Line data={chartData} />
}

```

## Key Source Files and Architecture

The WebSocket implementation spans several critical files in the libnyanpasu/clash-nyanpasu codebase:

- **[`frontend/interface/src/ipc/use-clash-web-socket.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-web-socket.ts)**: Core hook responsible for URL construction, authentication parameter injection, and WebSocket instance management using AHooks (lines 8-48).
- **[`frontend/interface/src/ipc/use-clash-info.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-info.ts)**: Provides the foundational `useClashInfo` hook that retrieves server credentials via SWR and the `/api/clash/info` endpoint.
- **[`frontend/interface/src/utils/index.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/utils/index.ts)**: Contains the `fetcher` utility function used by SWR for REST API communication.
- **Clash Core Endpoints**: The WebSocket client connects to four native Clash API endpoints: `/connections`, `/logs`, `/traffic`, and `/memory`, each streaming JSON-encoded real-time data.

## Summary

- **Credential Retrieval**: The system uses SWR to fetch server address and authentication tokens from `/api/clash/info` before establishing any WebSocket connections.
- **URL Construction**: The `useClashWebSocket` hook dynamically builds `ws://` URLs with encoded `token` query parameters to satisfy Clash core authentication requirements.
- **Multi-Stream Architecture**: Separate WebSocket connections handle `connections`, `logs`, `traffic`, and `memory` data streams, preventing head-of-line blocking between different data types.
- **React Integration**: AHooks' `useWebSocket` manages connection lifecycles, while components consume the `message` property to receive JSON payloads and update UI state in real time.
- **Lazy Initialization**: Empty string fallbacks prevent premature connection attempts before credentials are loaded, ensuring clean connection establishment.

## Frequently Asked Questions

### How does Clash Nyanpasu authenticate WebSocket connections to the Clash core?

Clash Nyanpasu authenticates WebSocket connections by URL-encoding the secret token obtained from `/api/clash/info` and appending it as a `token` query parameter to the WebSocket URL. The source code in [`frontend/interface/src/ipc/use-clash-web-socket.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-web-socket.ts) (lines 10-13) explicitly constructs this parameter using `encodeURIComponent(info?.secret || '')` because the Clash core rejects unauthenticated WebSocket upgrade requests.

### Why does the frontend use four separate WebSocket connections instead of one?

The frontend maintains four distinct WebSocket connections (for connections, logs, traffic, and memory) to leverage the Clash core's separate endpoint architecture. This design isolates data streams, preventing slow or high-volume streams (like logs) from interfering with critical real-time metrics (like traffic statistics), and allows components to subscribe only to the specific data they need.

### What happens if the Clash core credentials are not yet available when the component mounts?

If credentials are unavailable, the `useClashWebSocket` hook passes empty strings to the underlying `useWebSocket` calls from AHooks (lines 34-40). This keeps the WebSocket connections in a dormant state until the SWR-powered `useClashInfo` hook successfully retrieves the server address and secret token, at which point the URLs resolve and the connections establish automatically.

### Can components send data back to the Clash core through these WebSockets?

Yes, each WebSocket object returned by `useClashWebSocket` includes a `sendMessage` function provided by AHooks. While the primary use case in Clash Nyanpasu is consuming real-time data from the core, the bidirectional nature of WebSockets allows the frontend to transmit commands or configuration updates back to the Clash API when needed.