# Code example

{% tabs %}
{% tab title="Javascript" %}

```javascript
class SoccerWebSocket {
  constructor(wsToken) {
    this.wsToken = wsToken;
    this.ws = null;
    this.subscriptions = new Set();
  }

  connect() {
    this.ws = new WebSocket(`wss://ws.soccerfootball.info/?token=${this.wsToken}`);

    this.ws.onopen = () => {
      console.log('Connected to Soccer Football WebSocket');
      // Resubscribe if reconnecting
      this.subscriptions.forEach(sub => {
        this.subscribe(sub.channel, sub.scope);
      });
    };

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      this.handleMessage(message);
    };

    this.ws.onclose = (event) => {
      console.log(`Connection closed: ${event.code} - ${event.reason}`);
      if (event.code !== 1000) {
        // Attempt reconnection after 5 seconds
        setTimeout(() => this.connect(), 5000);
      }
    };

    this.ws.onerror = (error) => {
      console.error('WebSocket error:', error);
    };
  }

  subscribe(channel, scope) {
    const message = {
      action: 'subscribe',
      channel: channel,
      scope: scope
    };
    this.ws.send(JSON.stringify(message));
    this.subscriptions.add({ channel, scope });
  }

  unsubscribe(channel, scope) {
    const message = {
      action: 'unsubscribe',
      channel: channel,
      scope: scope
    };
    this.ws.send(JSON.stringify(message));
    this.subscriptions.delete({ channel, scope });
  }

  ping() {
    this.ws.send(JSON.stringify({ action: 'ping' }));
  }

  handleMessage(message) {
    switch (message.type) {
      case 'match_start':
        console.log('Match started:', message.data);
        break;
      case 'goal':
        console.log('Goal!', message.data);
        break;
      case 'halftime':
        console.log('Halftime:', message.data);
        break;
      case 'match_end':
        console.log('Match ended:', message.data);
        break;
      case 'stats_update':
        console.log('Stats update:', message.data);
        break;
      case 'odds_update':
        console.log('Odds update:', message.data);
        break;
      case 'pong':
        console.log('Pong received');
        break;
      case 'subscribed':
        console.log('Subscribed to:', message.channel);
        break;
      case 'error':
        console.error('Error:', message.message);
        break;
    }
  }

  disconnect() {
    if (this.ws) {
      this.ws.close(1000, 'Client disconnect');
    }
  }
}

// Usage
const client = new SoccerWebSocket('your-websocket-token');
client.connect();

// Subscribe to all MAIN events
client.subscribe('MAIN', 'all');

// Subscribe to a specific match
client.subscribe('STATS', 'match:12345');

// Subscribe to a specific league
client.subscribe('ODDS', 'league:67890');

// Keep connection alive
setInterval(() => client.ping(), 30000);
```

{% endtab %}

{% tab title="Python" %}

```python
import asyncio
import websockets
import json

class SoccerWebSocket:
    def __init__(self, ws_token):
        self.ws_token = ws_token
        self.ws = None
        self.subscriptions = set()

    async def connect(self):
        uri = f"wss://ws.soccerfootball.info/?token={self.ws_token}"

        async with websockets.connect(uri) as websocket:
            self.ws = websocket
            print("Connected to Soccer Football WebSocket")

            # Start message handler
            await self.handle_messages()

    async def handle_messages(self):
        async for message in self.ws:
            data = json.loads(message)
            await self.process_message(data)

    async def process_message(self, message):
        msg_type = message.get('type')

        if msg_type == 'match_start':
            print(f"Match started: {message.get('data')}")
        elif msg_type == 'goal':
            print(f"Goal! {message.get('data')}")
        elif msg_type == 'halftime':
            print(f"Halftime: {message.get('data')}")
        elif msg_type == 'match_end':
            print(f"Match ended: {message.get('data')}")
        elif msg_type == 'stats_update':
            print(f"Stats update: {message.get('data')}")
        elif msg_type == 'odds_update':
            print(f"Odds update: {message.get('data')}")
        elif msg_type == 'pong':
            print("Pong received")
        elif msg_type == 'subscribed':
            print(f"Subscribed to: {message.get('channel')}")
        elif msg_type == 'error':
            print(f"Error: {message.get('message')}")

    async def subscribe(self, channel, scope):
        message = {
            "action": "subscribe",
            "channel": channel,
            "scope": scope
        }
        await self.ws.send(json.dumps(message))
        self.subscriptions.add((channel, scope))

    async def unsubscribe(self, channel, scope):
        message = {
            "action": "unsubscribe",
            "channel": channel,
            "scope": scope
        }
        await self.ws.send(json.dumps(message))
        self.subscriptions.discard((channel, scope))

    async def ping(self):
        await self.ws.send(json.dumps({"action": "ping"}))

# Usage
async def main():
    client = SoccerWebSocket("your-websocket-token")

    async with websockets.connect(
        f"wss://ws.soccerfootball.info/?token={client.ws_token}"
    ) as ws:
        client.ws = ws

        # Subscribe to channels
        await client.subscribe("MAIN", "all")
        await client.subscribe("STATS", "match:12345")

        # Handle messages
        async for message in ws:
            data = json.loads(message)
            await client.process_message(data)

if __name__ == "__main__":
    asyncio.run(main())
```

{% endtab %}
{% endtabs %}

## Best Practices

1. **Handle reconnections**: Implement automatic reconnection with exponential backoff
2. **Renew tokens proactively**: Renew tokens 5 minutes before expiration
3. **Use ping/pong**: Send ping every 30 seconds to detect connection issues
4. **Limit subscriptions**: Only subscribe to channels and scopes you need
5. **Process messages quickly**: Don't block the message handler with heavy operations


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://info.soccerfootball.info/websocket/code-example.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
