# Quickstart (/en/realtime-media/rtc/get-started-sdk/web)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

This page provides a step-by-step guide on how to create a basic real-time app using the Agora RTC SDK. The same steps apply whether you're building voice calling, video calling, interactive live streaming, or broadcast streaming — only a few configuration values change based on your use case.

<Cards>
  <Card title="RTC SDK API examples" href="https://github.com/AgoraIO/API-Examples-Web" description="Sample projects for the Agora RTC Web SDK 4.x, covering basic and advanced examples for Vue and React." />
</Cards>

## Understand the tech

To start a real-time session, implement the following steps in your app:

* **Initialize the engine**: Before calling other APIs, create and initialize an engine instance.

* **Join a channel**: Call methods to create and join a channel.

  * **Join as a host**: A live streaming event has one or more hosts. A host publishes audio and video to the channel and can also subscribe to streams from other hosts.

  * **Join as audience**: Audience members can only subscribe to streams published by hosts.

  <CalloutContainer type="info">
    <CalloutTitle>
      Note
    </CalloutTitle>

    <CalloutDescription>
      For the voice calling and video calling use cases, each user joins as a host.
    </CalloutDescription>
  </CalloutContainer>

* **Send and receive audio and video**: Hosts publish streams to the channel. Audience members subscribe to audio and video streams published by hosts.

* For streaming applications, set the latency level based on your use case:

  * **Interactive live streaming**: Optimized for real-time interaction with ultra-low latency. Use this when hosts and audience need to interact quickly, such as in live Q\&A sessions, interactive classrooms, or auctions.

  * **Broadcast streaming**: Optimized for scalability with slightly higher latency. Use this for large-scale events where one-way broadcasting is sufficient, such as concerts, sports events, or news broadcasts.

![Realtime communication workflow](https://assets-docs.agora.io/images/video-sdk/video-call.svg)

## Prerequisites

* A camera and a microphone.
* A valid Agora account and project. See [Agora account management](/en/realtime-media/rtc/manage-agora-account) for details.
* A [supported browser](/en/realtime-media/rtc/reference/supported-platforms#mobile-browsers).
  Agora strongly recommends using the latest stable version of Google Chrome.
* [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)

## Set up your project

<Tabs defaultValue="new">
  <TabsList>
    <TabsTrigger value="new">
      Create a new project
    </TabsTrigger>

    <TabsTrigger value="existing">
      Add to an existing project
    </TabsTrigger>
  </TabsList>

  <TabsContent value="new">
    To initialize a new Vite project, take the following steps:

    1. Open a terminal and run the following command:

       ```
       npm create vite@latest agora_web_quickstart -- --template vanilla
       ```

       This creates a new folder named `agora_web_quickstart` and initializes a Vite project inside it using the `vanilla` JavaScript template.

    2. Navigate to the newly created folder. Download and set up dependencies for your project:

       ```
       cd agora_web_quickstart
       npm install
       ```

    3. Create a user interface for your project. The UI consists of buttons to join and leave a channel. Refer to [Create a user interface](#create-a-user-interface) to get a bare bones html layout.
  </TabsContent>

  <TabsContent value="existing">
    To add Realtime Communication to your existing project, take the following steps:

    1. Create a JavaScript file in your project's `src` folder to add `AgoraRTCClient` code that implements specific application logic.

    2. Add an HTML file to your project to create a user interface. The UI consists of buttons to join and leave a channel. Refer to [Create a user interface](#create-a-user-interface) to get a bare bones HTML layout.

    3. Include the JavaScript file in your HTML file.

       ```html
       <script type="module" src="/src/main.js"></script>
       ```
  </TabsContent>
</Tabs>

### Install the SDK

Add the RTC SDK to your project:

```bash
npm install agora-rtc-sdk-ng
```

## Implement Realtime Communication

This section guides you through the implementation of basic real-time audio and video interaction in your app.

The following figure illustrates the essential steps:

<Accordions>
  <Accordion title="Quick start sequence">
    ![Realtime Communication quick start sequence](https://assets-docs.agora.io/images/video-sdk/quick-start-sequence-web.svg)
  </Accordion>
</Accordions>

This guide includes [complete sample code](#complete-sample-code) that demonstrates implementing basic real-time interaction. To understand the core API calls in the sample code, review the following implementation steps.

### Import the `AgoraRTC` SDK

```js
import AgoraRTC from "agora-rtc-sdk-ng";
```

### Initialize an instance of `AgoraRTCClient`

Call [`createClient`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartc.html#createclient) to initialize an `AgoraRTCClient` object.
Set the [Channel mode](#channel-modes) and [Video encoding format](#video-encoding-formats) based on your use case.

Set the `mode`, `role`, and audience latency `level` according to your use case:

| Use case                   | Mode   | Role                 | Latency level            |
| -------------------------- | ------ | -------------------- | ------------------------ |
| Voice calling              | `rtc`  | N/A                  | N/A                      |
| Video calling              | `rtc`  | N/A                  | N/A                      |
| Interactive live streaming | `live` | `host` or `audience` | `2` (ultra-low, default) |
| Broadcast streaming        | `live` | `host` or `audience` | `1` (low)                |

<CalloutContainer type="info">
  <CalloutTitle>
    Note
  </CalloutTitle>

  <CalloutDescription>
    * In `rtc` mode, every user can publish and subscribe. In `live` mode, you assign each user a role: hosts publish and subscribe, audience members only subscribe.
    * The latency `level` only applies to the audience role, set through `setClientRole`, and affects your [pricing](/en/realtime-media/rtc/reference/pricing#subscription-packages) tier.
  </CalloutDescription>
</CalloutContainer>

The following example shows the configuration for interactive live streaming with the host role:

```javascript
// RTC client instance
let client = null;

// Initialize the AgoraRTC client
function initializeClient() {
    // Set mode to "live" for streaming use cases, or "rtc" for calling use cases (see table above)
    // Set role to "host" or "audience" according to your use case
    client = AgoraRTC.createClient({ mode: "live", codec: "vp8", role: "host" });
    setupEventListeners();
}
```

### Join a channel

To join a channel, call `join` with the following parameters:

* **App ID**: The [App ID](/en/realtime-media/rtc/manage-agora-account#get-the-app-id) for your project.

* **Channel name**: The name of the channel to join. Clients that pass the same channel name join the same channel. If a channel with the specified name does not exist, it is created when the first user joins.

* **Authentication token**: A dynamic key that authenticates a user when the client joins a channel. In a production environment, you obtain a token from a [token server](/en/realtime-media/rtc/build/authenticate-users/deploy-token-server) in your security infrastructure. For the purpose of this guide [Generate a temporary token](/en/realtime-media/rtc/manage-agora-account#generate-temporary-tokens).

* **User ID**: A 32-bit signed integer that identifies a user in the channel. You can specify a unique user ID for each user yourself. If you set the user ID to `0` when joining a channel, the SDK generates a random number for the user ID.

When you join as a host, you can publish local media streams in the channel; you can also subscribe to streams published by other hosts. As an audience member, you may only subscribe to media streams published by hosts.

The `mode` and `role` you set when you [Initialize an instance of `AgoraRTCClient`](#initialize-an-instance-of-agorartcclient) determine what a user can do after joining.

```javascript
// Join a channel and publish local media
async function joinChannel() {
    await client.join(appId, channel, token, uid);
    await createLocalMediaTracks();
    displayLocalVideo();
    publishLocalTracks();
}
```

For the audience role in `live` mode, change the role and latency level after joining by calling `setClientRole`:

```javascript
// Low audience latency level; use 2 for ultra-low latency
let clientRoleOptions = { level: 1 };
client.setClientRole("audience", clientRoleOptions);
```

### Create local media tracks

To set up the necessary local media tracks:

* Call `createMicrophoneAudioTrack` to create a local audio track.
* Call `createCameraVideoTrack` to create a local Video track.

```javascript
// Declare variables for local tracks
let localAudioTrack = null;
let localVideoTrack = null;

// Create local audio and video tracks
async function createLocalMediaTracks() {
    localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
    localVideoTrack = await AgoraRTC.createCameraVideoTrack();
}
```

### Publish local media tracks

To make the created audio and video tracks available for other users in the channel, use the `publish` method.

```javascript
async function publishLocalTracks() {
    await client.publish([localAudioTrack, localVideoTrack]);
}
```

See [Local audio and video tracks](#local-audio-and-video-tracks) to learn more about local tracks.

### Set up event listeners

Use the `on` method to register event listeners for SDK events. The SDK triggers the `user-published` event when a user publishes an audio track in the channel. Similarly, it triggers the `user-unpublished` event when a user leaves the channel, goes offline, or unpublishes a media track.

```javascript
// Handle client events
function setupEventListeners() {
    // Declare event handler for "user-published"
    client.on("user-published", async (user, mediaType) => {
        // Subscribe to media streams
        await client.subscribe(user, mediaType);
        if (mediaType === "video") {
            // Specify the ID of the DOM element or pass a DOM object.
            user.videoTrack.play("<Specify a DOM element>");
        }
        if (mediaType === "audio") {
            user.audioTrack.play();
        }
    });

    // Handle the "user-unpublished" event to unsubscribe from the user's media tracks
    client.on("user-unpublished", async (user) => {
        const remotePlayerContainer = document.getElementById(user.uid);
        remotePlayerContainer && remotePlayerContainer.remove();
    });
}
```

* After successfully unsubscribing, the SDK releases the corresponding `RemoteTrack` object. This automatically removes the video playback element and stops audio playback.
* If a remote user actively stops publishing, the local user receives the `user-unpublished` callback. Upon receiving this callback, the SDK automatically releases the corresponding `RemoteTrack` object, so you do not need to call `unsubscribe` again.
* The `unsubscribe` method is asynchronous and should be used with `Promise` or `async/await`.

<CalloutContainer type="info">
  <CalloutTitle>
    Note
  </CalloutTitle>

  <CalloutDescription>
    To ensure that you receive all RTC SDK events, set up event listeners before joining a channel.
  </CalloutDescription>
</CalloutContainer>

For more information about other `AgoraRTCClient` events, refer to the [API reference](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#event_channel_media_relay_event).

### Display the local video

To play the local video, use the `play` method of the local video track. Pass an element ID or a DOM element from your UI where you want to render the video.

```javascript
// Display local video
function displayLocalVideo() {
    const localPlayerContainer = document.createElement("div");
    localPlayerContainer.id = uid;
    localPlayerContainer.textContent = `Local user ${uid}`;
    localPlayerContainer.style.width = "640px";
    localPlayerContainer.style.height = "480px";
    document.body.append(localPlayerContainer);
    localVideoTrack.play(localPlayerContainer);
}
```

### Display remote video

To display the remote video, call the `play` method of the remote user's `videoTrack` and pass in either the element ID or a DOM element from your UI where you want to render the video.

```js
// Display remote user's video
function displayRemoteVideo(user) {
    const remotePlayerContainer = document.createElement("div");
    remotePlayerContainer.id = user.uid.toString();
    remotePlayerContainer.textContent = `Remote user ${user.uid}`;
    remotePlayerContainer.style.width = "640px";
    remotePlayerContainer.style.height = "480px";
    document.body.append(remotePlayerContainer);
    user.videoTrack.play(remotePlayerContainer);
}
```

### Leave the channel

To exit the channel, close local audio and video tracks and call `leave`.

```javascript
// Leave the channel and clean up
async function leaveChannel() {
    // Stop the local media tracks to release the microphone and camera resources
    if (localAudioTrack) {
        localAudioTrack.close();
        localAudioTrack = null;
    }
    if (localVideoTrack) {
        localVideoTrack.close();
        localVideoTrack = null;
    }
    // Leave the channel
    await client.leave();
}
```

### Complete sample code

A complete code sample demonstrating the basic process of real-time interaction is provided here for your reference. To use the sample, copy the following code to the JavaScript file in the project's `src` folder.

<Accordions>
  <Accordion title="Complete sample code for Realtime Communication">
    ```javascript
    import AgoraRTC from "agora-rtc-sdk-ng";

    // RTC client instance
    let client = null;

    // Declare variables for the local tracks
    let localAudioTrack = null;
    let localVideoTrack = null;

    // Connection parameters
    let appId = "<-- Insert app ID -->";
    let channel = "<-- Insert channel name -->";
    let token = "<-- Insert token -->";
    let uid = 0; // User ID

    // Initialize the AgoraRTC client
    function initializeClient() {
        // Set mode to "live" for streaming use cases, or "rtc" for calling use cases
        // Set role to "host" or "audience" according to your use case
        client = AgoraRTC.createClient({ mode: "live", codec: "vp8", role: "host" });
        setupEventListeners();
    }

    // Handle client events
    function setupEventListeners() {
        client.on("user-published", async (user, mediaType) => {
            await client.subscribe(user, mediaType);
            console.log("subscribe success");

            if (mediaType === "video") {
                displayRemoteVideo(user);
            }

            if (mediaType === "audio") {
                user.audioTrack.play();
            }
        });

        client.on("user-unpublished", (user) => {
            const remotePlayerContainer = document.getElementById(user.uid);
            remotePlayerContainer && remotePlayerContainer.remove();
        });
    }

    // Join a channel and publish local media
    async function joinChannel() {
        await client.join(appId, channel, token, uid);
        await createLocalTracks();
        await publishLocalTracks();
        displayLocalVideo();
        console.log("Publish success!");
    }

    // Create local audio and video tracks
    async function createLocalTracks() {
        localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
        localVideoTrack = await AgoraRTC.createCameraVideoTrack();
    }

    // Publish local audio and video tracks
    async function publishLocalTracks() {
        await client.publish([localAudioTrack, localVideoTrack]);
    }

    // Display local video
    function displayLocalVideo() {
        const localPlayerContainer = document.createElement("div");
        localPlayerContainer.id = uid;
        localPlayerContainer.textContent = `Local user ${uid}`;
        localPlayerContainer.style.width = "640px";
        localPlayerContainer.style.height = "480px";
        document.body.append(localPlayerContainer);
        localVideoTrack.play(localPlayerContainer);
    }

    // Display remote video
    function displayRemoteVideo(user) {
        const remoteVideoTrack = user.videoTrack;
        const remotePlayerContainer = document.createElement("div");
        remotePlayerContainer.id = user.uid.toString();
        remotePlayerContainer.textContent = `Remote user ${user.uid}`;
        remotePlayerContainer.style.width = "640px";
        remotePlayerContainer.style.height = "480px";
        document.body.append(remotePlayerContainer);
        remoteVideoTrack.play(remotePlayerContainer);
    }

    // Leave the channel and clean up
    async function leaveChannel() {
        // Close local tracks
        localAudioTrack.close();
        localVideoTrack.close();

        // Remove local video container
        const localPlayerContainer = document.getElementById(uid);
        localPlayerContainer && localPlayerContainer.remove();

        // Remove all remote video containers
        client.remoteUsers.forEach((user) => {
            const playerContainer = document.getElementById(user.uid);
            playerContainer && playerContainer.remove();
        });

        // Leave the channel
        await client.leave();
    }

    // Set up button click handlers
    function setupButtonHandlers() {
        document.getElementById("join").onclick = joinChannel;
        document.getElementById("leave").onclick = leaveChannel;
    }

    // Start the basic call
    function startBasicCall() {
        initializeClient();
        window.onload = setupButtonHandlers;
    }

    startBasicCall();
    ```
  </Accordion>
</Accordions>

### Create a user interface

Open `index.html` in the project's root folder and replace the contents with the following code to implement a basic client user interface:

### Sample code to create the user interface

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Web SDK Video Quickstart</title>
</head>
<body>
    <h2 class="left-align">Web SDK Video Quickstart</h2>
    <div class="row">
        <div>
            <button type="button" id="join">Join</button>
            <button type="button" id="leave">Leave</button>
        </div>
    </div>
    <!-- Include the JavaScript file -->
    <script type="module" src="/src/main.js"></script>
</body>
</html>
```

## Test the sample code

Take the following steps to run and test the sample code:

1. In your `.js` file, update the values for `appId`, and `token` with values from Agora Console. Use the same `channel` name you used to generate the token.

2. To start the development server, use the following command:

   ```shell
   npm run dev
   ```

3. Open your browser and navigate to the URL displayed in your terminal, for example, `http://localhost:5173`.

   You see the following page:

   ![](https://assets-docs.agora.io/images/video-sdk/quickstart-ui-web.png)

4. On a second device, repeat the previous steps to install and launch the client. Alternatively, use the [Web demo](https://webdemo.agora.io/basicVideoCall/index.html) or clone the [sample project on Github](https://github.com/AgoraIO/API-Examples-Web) to join the same channel and test the following use-cases:

   1. Click **Join** to join the channel.
   2. Enter the same app ID, channel name, and temporary token.

      <CalloutContainer type="info">
        <CalloutTitle>
          Note
        </CalloutTitle>

        <CalloutDescription>
          * Run the web app on a local server (localhost) for testing purposes only. When deploying to a production environment, use the HTTPS protocol.
          * Due to browser security policies that restrict HTTP addresses to 127.0.0.1, the Agora Web SDK only supports HTTPS protocol and `http://localhost` (`http://127.0.0.1`). Please do not use the HTTP protocol to access your project, except for `http://localhost` (`http://127.0.0.1`).
        </CalloutDescription>
      </CalloutContainer>

## Reference

This section contains content that completes the information on this page, or points you to documentation that explains other aspects of this product.

* If a firewall is deployed in your network environment, refer to [Connect with Cloud Proxy](/en/realtime-media/rtc/build/manage-connection-and-quality/cloud-proxy) to use Agora services normally.

### Next steps

After implementing the quickstart sample, read the following documents to learn more:

* To ensure communication security in a test or production environment, best practice is to obtain and use a token from an authentication server. For details, see [Secure authentication with tokens](/en/realtime-media/rtc/build/authenticate-users/authentication-workflow).

### Sample project

* [Build a NextJS Video Call App](https://www.agora.io/en/blog/build-a-next-js-video-call-app/)

* Agora provides open source sample projects on [GitHub](https://github.com/AgoraIO/API-Examples-Web) for your reference. Download or view the [basicVideoCall](https://github.com/AgoraIO/API-Examples-Web/tree/main/src/example/basic/basicVideoCall) project for a more detailed example.

### API reference

* [`AgoraRTC.createClient`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartc.html#createclient)
* [`IAgoraRTCRemoteUser`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcremoteuser.html)
* [`play`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iremoteaudiotrack.html#play)
* [`join`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#join)
* [`createMicrophoneAudioTrack`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartc.html#createmicrophoneaudiotrack)
* [`createCameraVideoTrack`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartc.html#createcameravideotrack)
* [`publish`](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#publish)
* [AgoraRTCClient events](https://api-ref.agora.io/en/video-sdk/web/4.x/interfaces/iagorartcclient.html#event_channel_media_relay_event)

### Channel modes

The RTC SDK supports the following channel modes:

* `rtc`: Communication use-case
* `live`: Live broadcast use-case

#### Communication use-case

It is suitable for use-cases where all users in the channel need to communicate with each other and the total number of users is not too large, such as multi-person conferences and online chats.

#### Live broadcast use-case

It is suitable for use-cases where there are few publishers but many subscribers. In this use-case, the SDK defines two user roles: audience (default) and host. Hosts can send and receive audio and video, but audience cannot send and may only receive audio and video. You can specify user roles by setting the parameters `createClient` of role, or you can call `setClientRole` to dynamically modify user roles.

### Video encoding formats

You can set the `codec` parameter in the `createClient` method to the following video encoding formats:

* `vp8` (VP8)
* `h264` (H.264)
* `vp9` (VP9)

This setting only affects the video encoding format of the host. For the audience, as long as their device and browser support the decoding of this format, the subscription can be completed normally.

Support for these formats may vary across browsers and devices. The following table lists the `codec` formats supported by different browsers for reference:

| Browser            | VP8 | H.264                | VP9                     |
| :----------------- | --- | -------------------- | ----------------------- |
| Desktop Chrome 58+ | ✔   | ✔                    | ✔                       |
| Firefox 56+        | ✔   | ✔                    | ✔(Requires Firefox 69+) |
| Safari 12.1+       | ✔   | ✔                    | ✔(Requires Safari 16+)  |
| Safari \< 12.1     | ✘   | ✔                    | ✘                       |
| AndroidChrome 58+  | ✔   | No clear information | ✔(Requires Chrome 68+)  |

<CalloutContainer type="info">
  <CalloutTitle>
    Note
  </CalloutTitle>

  <CalloutDescription>
    * H.264 support on Firefox depends on the `OpenH264` video codec plug-in from Cisco Systems, Inc.
    * For Chrome, support for H.264 on Android devices varies based on device hardware compatibility with hardware codecs mandated by Chrome.
  </CalloutDescription>
</CalloutContainer>

### Local audio and video tracks

The SDK uses a hierarchy where all local track objects derive from the `LocalTrack` base class. This class defines the common behavior for all local tracks. Specific track types, such as `LocalAudioTrack` and `LocalVideoTrack` inherit from `LocalTrack` and extend its functionality.

To publish a local track, you call the `publish` method of the client with the `LocalTrack` object as an input parameter. This approach makes publishing a track independent of how you create your local track.

There are two main types of local tracks: `LocalAudioTrack` and `LocalVideoTrack` for publishing audio and video, respectively. Each type of `LocalTrack` comes with its own set of tools. For example, `LocalAudioTrack` lets you control the volume, while `LocalVideoTrack` has functions for customizing video.

The SDK includes more specific classes based on `LocalAudioTrack` and `LocalVideoTrack`. For example, the `CameraVideoTrack`, is a type of `LocalVideoTrack` that you can use to publish video from your camera. It comes with extra features for controlling the camera and adjusting video quality.

The following diagram shows the relationship between the `LocalTrack` classes:

![ILocalTrack](https://assets-docs.agora.io/images/video-sdk/ILocalTrack-web.png)

### Other integration methods

When you use `npm` to install the Web SDK, you can enable tree shaking to reduce the size of the app after integration. For details, see [Using tree shaking](/en/realtime-media/rtc/build/optimize-and-operate/app-size-optimization#use-tree-shaking).

In addition to using `npm` to install the Web SDK, you can also use the following methods:

* In the project HTML file, add the following tag to obtain the SDK from CDN:

  ```html
  <script src="https://download.agora.io/sdk/release/AgoraRTC_N-4.24.6.js"></script>
  ```

* Download the RTC SDK package locally, save the `.js` files in the SDK package to the project directory, and then add the following tag to the project HTML file:

  ```html
  <script src="./AgoraRTC_N-4.24.6.js"></script>
  ```

Visit the [Download](/en/api-reference/sdks?platform=web) page to obtain the link for the latest SDK version.

### Frequently asked questions

**Why do I get a `digital envelope routines::unsupported` error when running the quickstart project locally?**

This issue arises in projects configured with `webpack` for local execution due to changes in Node.js 16 and above. The modifications in Node.js, particularly its dependency on OpenSSL (detailed in the [node issue](https://github.com/nodejs/node/issues/29817)), impact the local development environment dependencies of the project. Refer to the [webpack issue](https://github.com/webpack/webpack/issues/14532) for details.

Use one of the following solutions to resolve the issue:

* Run the following command to set a temporary environment variable (Recommended):

  ```shell
  export NODE_OPTIONS=--openssl-legacy-provider
  ```

* Temporarily switch to a lower version of Node.js.

### See also

* [SDK error codes](/en/realtime-media/rtc/reference/error-codes)

    
  
      
  
      
  
      
  
      
  
      
  
      
  
      
  
      
  
