# ActiveFence Video Content Moderation (/en/realtime-media/marketplace/build/add-moderation-and-intelligence/activefence)

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

[ActiveFence](https://www.activefence.com/) provides trust and safety solutions to protect online platforms and their users from malicious behavior and content. By integrating ActiveFence capabilities in your app, you can design the exact content moderation solution you need. Content moderation is powered by AI-driven automated detection for text, audio, image, and video content, enabling you to moderate, enforce policies, manage user flags, and send notifications across multiple abuse areas and languages.

<_PlatformTabsGroup groupMode="structured" canonicalPlatform="web" platforms="[&#x22;android&#x22;,&#x22;ios&#x22;,&#x22;web&#x22;,&#x22;flutter&#x22;,&#x22;react-native&#x22;]" showTabs="true">
  <_PlatformPanel platform="android">
    <_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />

    The following figure shows the ActiveFence workflow to moderate content sent by a specific user to a channel:

    ![ActiveFence workflow](https://assets-docs.agora.io/images/extensions-marketplace/active-fence.svg)

    This page shows you how to integrate and use the ActiveFence content detection and moderation extension in your app.

    ## Prerequisites [#prerequisites]

    The development environment requirements are as follows:

    * Android Studio 4.1 or later.
    * A physical device (not an emulator) running Android 5.0 or later.
    * Implemented the [SDK quickstart](../../../video/quickstart.mdx).
    * If you use RTC SDK tokens, ensure that you are using AccessToken2 to enable ActiveFence video content moderation.

    ## Project setup [#project-setup]

    In order to configure ActiveFence:

    1. Set up your ActiveFence account.
       * In Agora Extensions Marketplace, select ActiveFence, then click **Activate Your Account**; or contact `extensions.marketplace@agora.io` to activate the extension.
       * Follow the activation email instructions to activate your ActiveFence account.
    2. Configure your ActiveFence API key.
       * In ActiveFence, open **Account Settings**.
       * Click **Data Management** > **ActiveFence API Keys** and create a key.
       * Save the key securely and share the key information with Agora so the services can be connected.
    3. Connect your app to your ActiveFence account.
       * Email `support@agora.io` and provide your company name, company email, Agora App ID, and ActiveFence API key.
    4. Customize your callback fields.

       * In ActiveFence, open **Account Settings** > **Moderation Capabilities** > **Custom Fields**.
       * Add editable fields for `cname`, `requestId`, `sid`, `source`, `timestamp`, and `uid`.

       | Title & Key | Type   | Meaning                                    |
       | :---------- | :----- | :----------------------------------------- |
       | `cname`     | Text   | RTC channel name                           |
       | `requestId` | Text   | Request ID of the screenshot               |
       | `sid`       | Text   | Session ID                                 |
       | `source`    | Text   | Source of screenshot (`agora`)             |
       | `timestamp` | Number | Timestamp, for example `20230614050206430` |
       | `uid`       | Number | User ID (unique in a channel)              |

       ![Add an editable field](https://assets-docs.agora.io/images/extensions-marketplace/active-fence-add-an-editable-field.png)

    The editable fields are:

    | Title and key | Type   | Meaning                                       |
    | ------------- | ------ | --------------------------------------------- |
    | `cname`       | Text   | RTC channel name                              |
    | `requestId`   | Text   | Request ID of the screenshot                  |
    | `sid`         | Text   | Session ID                                    |
    | `source`      | Text   | Source of the screenshot, for example `agora` |
    | `timestamp`   | Number | Timestamp, for example `20230614050206430`    |
    | `uid`         | Number | User ID, unique in a channel                  |

    5. Configure action webhooks and workflows in ActiveFence.
    6. Invite users and start moderating content in ActiveFence.

    ## Integrate the extension [#integrate-the-extension]

    Now that ActiveFence is activated, set up your webhook receiver and then enable content inspection in your SDK project.

    ### Set up your webhook [#set-up-your-webhook]

    To react to content moderation callbacks, create a server that receives and interprets the webhook data. For example:

    1. Open [agora-activefence-kicker](https://github.com/AgoraIO-Community/agora-activefence-kicker) and deploy the server with its one-click flow.
    2. Add the deployment link plus `/kick/` to the webhook URL for the desired event in ActiveFence.

    ### Initialize `ContentInspectConfig` [#initialize-contentinspectconfig]

    Set up the inspect config inside `ContentInspectModule`. If you use a string UID to join the channel and want to receive it in the webhook callback, pass the string UID to `extraInfo` inside `ContentInspectConfig`.

    ```kotlin
    val contentInspectModule = ContentInspectModule()
    contentInspectModule.type = ContentInspectConfig.CONTENT_INSPECT_TYPE_IMAGE_MODERATION
    contentInspectModule.interval = 5
    val contentInspectConfig = ContentInspectConfig()
    contentInspectConfig.modules[0] = contentInspectModule
    contentInspectConfig.moduleCount = 1
    contentInspectConfig.extraInfo = "YourExtraInfo"
    ```

    ### Apply `ContentInspectConfig` [#apply-contentinspectconfig]

    Enable content inspection after joining a channel and after the local video is published and played. If you need support for taking screenshots for multiple video streams and uploading them, use `enableContentInspectEx`.

    ```kotlin
    val returnVal = agoraEngine?.enableContentInspect(true, contentInspectConfig)
    val returnValEx = agoraEngine?.enableContentInspectEx(enabled, config = config, connection = connection)
    ```

    ### Catch banning events [#catch-banning-events]

    To know when your local user is banned from the scene, use the connection state callback:

    ```kotlin
    override fun onConnectionStateChanged(state: Int, reason: Int) {
      super.onConnectionStateChanged(state, reason)
      if (
        state == Constants.CONNECTION_STATE_FAILED &&
        reason == Constants.CONNECTION_CHANGED_BANNED_BY_SERVER
      ) {
        showMessage("Stream banned by the server")
      }
    }
    ```

    ## Reference [#reference]

    * [Agora Content Inspect Moderation Showcase](https://github.com/AgoraIO-Community/Agora-ActiveFence-Android)
    * [Multi-channel methods](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_irtcengineex.html)
    * [ActiveFence documentation](https://docs.activefence.com/#section/About-This-Guide)
    * [Channel Management REST API](../../../broadcast-streaming/reference/channel-management-api/overview.md)

    <_PlatformProcessedMarker close="true" />
  </_PlatformPanel>

  <_PlatformPanel platform="ios">
    <_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />

    The following figure shows the ActiveFence workflow to moderate content sent by a specific user to a channel:

    ![ActiveFence workflow](https://assets-docs.agora.io/images/extensions-marketplace/active-fence.svg)

    This page shows you how to integrate and use the ActiveFence content detection and moderation extension in your app.

    ## Prerequisites [#prerequisites-1]

    * Xcode 9.0 or later.
    * A physical device (not an emulator) running iOS 9.0 or later.
    * Implemented the [SDK quickstart](../../../video/quickstart.mdx).
    * If you use RTC SDK tokens, ensure that you are using AccessToken2 to enable ActiveFence video content moderation.

    ## Project setup [#project-setup-1]

    Complete the same ActiveFence account, API key, webhook, and workflow configuration described in the Android section.

    ## Integrate the extension [#integrate-the-extension-1]

    ### Set up your webhook [#set-up-your-webhook-1]

    Create a server that receives and interprets the webhook data, for example with [agora-activefence-kicker](https://github.com/AgoraIO-Community/agora-activefence-kicker).

    ### Initialize `AgoraContentInspectConfig` [#initialize-agoracontentinspectconfig]

    Set up the inspect config inside `ContentInspectManager`. If you use a string UID to join the channel and want to receive it in the webhook callback, pass the string UID to `extraInfo` inside `AgoraContentInspectConfig`.

    ```swift
    var inspectConfig: AgoraContentInspectConfig = {
      let module = AgoraContentInspectModule()
      module.type = .imageModeration
      module.interval = 5

      let config = AgoraContentInspectConfig()
      config.modules = [module]
      config.extraInfo = "YourExtraInfo"
      return config
    }()
    ```

    ### Apply `AgoraContentInspectConfig` [#apply-agoracontentinspectconfig]

    Enable content inspection after joining a channel and after the local video is published and played. To support taking screenshots for multiple video streams and uploading them, use `enableContentInspectEx`.

    ```swift
    self.agoraEngine.enableContentInspect(true, config: self.inspectConfig)
    self.agoraEngine.enableContentInspectEx(enabled, config: config, connection: connection)
    ```

    ### Catch banning events [#catch-banning-events-1]

    ```swift
    func rtcEngine(
      _ engine: AgoraRtcEngineKit,
      connectionChangedTo state: AgoraConnectionState,
      reason: AgoraConnectionChangedReason
    ) {
      if state == .failed, reason == .reasonBannedByServer {
        isBanned = true
      }
    }
    ```

    ## Reference [#reference-1]

    * [Agora Content Inspect Moderation Showcase](https://github.com/AgoraIO-Community/Agora-ActiveFence-iOS)
    * [ActiveFence documentation](https://docs.activefence.com/#section/About-This-Guide)

    <_PlatformProcessedMarker close="true" />
  </_PlatformPanel>

  <_PlatformPanel platform="web">
    <_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />

    [ActiveFence](https://www.activefence.com/) provides trust and safety solutions to protect online platforms and their users from malicious behavior and content. The following figure shows the ActiveFence moderation workflow for channel content:

    ![ActiveFence workflow](https://assets-docs.agora.io/images/extensions-marketplace/active-fence.svg)

    ## Prerequisites [#prerequisites-2]

    * A [supported browser](../../reference/supported-platforms.mdx).
    * Implemented the [SDK quickstart](../../../video/quickstart.mdx).
    * Completed the ActiveFence account, API key, webhook, and workflow configuration described above.

    ## Integrate the extension [#integrate-the-extension-2]

    ### Set up an event listener to check status [#set-up-an-event-listener-to-check-status]

    ```javascript
    agoraEngine.on("image-moderation-connection-state-change", (cur, prev) => {
      console.log("AF status:", "prev", prev, "cur", cur);
    });
    ```

    ### Enable image moderation [#enable-image-moderation]

    If you use a string UID to join the channel and want to receive it in the webhook callback, pass the string UID as `extraInfo`.

    ```javascript
    agoraEngine
      .setImageModeration(true, "YourExtraInfo", { interval: 1000 })
      .then((e) => console.log("AF enabled", e));
    ```

    ### Show an alert when the current user is kicked [#show-an-alert-when-the-current-user-is-kicked]

    ```javascript
    agoraEngine.on("connection-state-change", (cur, prev, reason) => {
      console.log("connection:", "prev", prev, "cur", cur, "reason:", reason);
      if (reason === ConnectionDisconnectedReason.UID_BANNED) {
        if (confirm("You are kicked from this channel, reload?")) {
          window.location.reload();
        }
      }
    });
    ```

    ## Reference [#reference-2]

    * [ActiveFence sample web project](https://github.com/EkaanshArora/agora-activefence/)
    * [ActiveFence documentation](https://docs.activefence.com/#section/About-This-Guide)

    <_PlatformProcessedMarker close="true" />
  </_PlatformPanel>

  <_PlatformPanel platform="flutter">
    <_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />

    ## Prerequisites [#prerequisites-3]

    * [Flutter](https://docs.flutter.dev/get-started/install) 2.0.0 or higher.
    * Dart 2.15.1 or higher.
    * A Flutter editor such as Android Studio, IntelliJ, or VS Code.
    * Implemented the [SDK quickstart](../../../video/quickstart.mdx).

    ## Integrate the extension [#integrate-the-extension-3]

    ### Initialize `ContentInspectConfig` [#initialize-contentinspectconfig-1]

    ```dart
    const contentInspectModule = ContentInspectModule(
      type: ContentInspectType.contentInspectModeration,
      interval: 5,
    );
    const contentInspectConfig = ContentInspectConfig(
      modules: [contentInspectModule],
      moduleCount: 1,
      extraInfo: 'YourExtraInfo',
    );
    ```

    ### Apply `ContentInspectConfig` [#apply-contentinspectconfig-1]

    ```dart
    var returnVal = await agoraEngine.enableContentInspect(
      enabled: true,
      config: contentInspectConfig,
    );
    ```

    ### Catch banning events [#catch-banning-events-2]

    ```dart
    agoraEngine.registerEventHandler(RtcEngineEventHandler(
      onConnectionStateChanged: (connection, state, reason) {
        if (
          state == ConnectionStateType.connectionStateFailed &&
          reason == ConnectionChangedReasonType.connectionChangedBannedByServer
        ) {
          debugPrint('Stream banned by the server');
        }
      },
    ));
    ```

    <_PlatformProcessedMarker close="true" />
  </_PlatformPanel>

  <_PlatformPanel platform="react-native">
    <_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="react-native" />

    ## Prerequisites [#prerequisites-4]

    * React Native 0.60 or later.
    * Node 10 or later.
    * Implemented the [SDK quickstart](../../../video/quickstart.mdx).

    ## Integrate the extension [#integrate-the-extension-4]

    ### Initialize `ContentInspectConfig` [#initialize-contentinspectconfig-2]

    ```tsx
    const contentInspectModule: ContentInspectModule = {
      type: ContentInspectType.ContentInspectModeration,
      interval: 5,
    };
    const contentInspectConfig: ContentInspectConfig = {
      modules: [contentInspectModule],
      moduleCount: 1,
      extraInfo: 'YourExtraInfo',
    };
    ```

    ### Apply `ContentInspectConfig` [#apply-contentinspectconfig-2]

    ```tsx
    const returnVal = agoraEngine?.enableContentInspect(true, contentInspectConfig);
    ```

    ### Catch banning events [#catch-banning-events-3]

    ```tsx
    agoraEngine?.addListener(
      'onConnectionStateChanged',
      (connection, state, reason) => {
        if (
          state === ConnectionStateType.ConnectionStateFailed &&
          reason === ConnectionChangedReasonType.ConnectionChangedBannedByServer
        ) {
          console.log('Stream banned by the server');
        }
      },
    );
    ```

    <_PlatformProcessedMarker close="true" />
  </_PlatformPanel>
</_PlatformTabsGroup>
