> ## Documentation Index
> Fetch the complete documentation index at: https://gcore.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Invalid user agent and Unknown user agent

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).map(c => {
    if (!c || !c.props) return null;
    if (c.props.id) return c;
    const inner = c.props.children;
    if (inner && inner.props && inner.props.id) return inner;
    return null;
  }).filter(Boolean);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
    window.dispatchEvent(new Event("scroll"));
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    <p>These two WAAP policies work together to identify and block requests that lack a standard user-agent parameter. If the agent is missing, this can indicate that an illegitimate client is being used.</p>

    <p>Most browsers provide user agent information across the network to validate a client's authenticity and purpose. User agent strings typically follow this syntax:</p>

    `User-Agent: <product> / <product-version> <comment>`

    Where:

    * `<product>`: A product identifier — its name or development codename.
    * `<product-version>`: Version number of the product.
    * `<comment>`: Comments containing additional details — sub-product information.

    <Accordion title="Example formats of generated user agents">
      This is the common format of a user agent generated by a web browser:

      `User-Agent: Mozilla/5.0 (<system-information>) <platform> (<platform-details>) <extensions>`

      The following is an example of a user agent generated by a Windows XP user browsing a website via Google Chrome:

      `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36`

      This user agent indicates that the user is using Windows 10 (Windows NT 10.0), a 64-bit system (Win64; x64), and the latest version of Chrome (98.0.4758.102) at the time of browsing.

      `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36`

      This user agent indicates that the user is using macOS (Macintosh), specifically version 10.15.7 (Intel Mac OS X 10\_15\_7), and the latest version of Chrome (98.0.4758.102) at the time of browsing.
    </Accordion>

    <p>Both policies are part of the [Anti-automation and bot protection](/waap/waap-policies/anti-automation-and-bot-protection) group and are enabled by default. To change the state of a policy, navigate to the [Gcore Customer Portal](https://portal.gcore.com):</p>

    1. Navigate to **WAAP** > **Bot Management**.
    2. In the domain dropdown at the top right of the page, select the domain.
    3. Open the **Bot Attacks** tab.
    4. Find the **Invalid user agent** or **Unknown user agent** policy and click the dropdown next to it to enable or disable it.
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>The [Policies](/api-reference/waap#policies) endpoints manage the Invalid user agent and Unknown user agent rules. Both policies are enabled by default and belong to the Anti-automation and bot protection ruleset. Response examples include only the fields used in each step.</p>

    <Info>
      An [API token](/account-settings/api-tokens) is required, along with the ID of a [WAAP-protected domain](/waap/getting-started/configure-waap-for-a-domain) and the [Python](/developer-tools/sdks/python) or [Go](/developer-tools/sdks/go) SDK installed for SDK examples.
    </Info>

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export WAAP_DOMAIN_ID="{YOUR_DOMAIN_ID}"
    ```

    ## View policy states

    <p>Retrieve the current state of the Invalid user agent and Unknown user agent policies for a domain.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import gcore
        import os

        client = gcore.Gcore(api_key=os.environ["GCORE_API_KEY"])
        domain_id = int(os.environ["WAAP_DOMAIN_ID"])

        TARGET_IDS = {"S3008869", "S3008870"}

        rule_sets = client.waap.domains.list_rule_sets(domain_id)
        aa_set = next(
            rs for rs in rule_sets if rs.resource_slug == "anti-automation-bot-protection"
        )

        for policy in aa_set.rules:
            if policy.id in TARGET_IDS:
                status = "enabled" if policy.mode else "disabled"
                print(f"{policy.name}: {status} ({policy.id})")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"
            "strconv"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/option"
        )

        func main() {
            client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))
            domainID, _ := strconv.ParseInt(os.Getenv("WAAP_DOMAIN_ID"), 10, 64)

            targetIDs := map[string]bool{"S3008869": true, "S3008870": true}

            ruleSets, _ := client.Waap.Domains.ListRuleSets(context.Background(), domainID)
            for _, rs := range *ruleSets {
                if rs.ResourceSlug == "anti-automation-bot-protection" {
                    for _, policy := range rs.Rules {
                        if targetIDs[policy.ID] {
                            status := "disabled"
                            if policy.Mode {
                                status = "enabled"
                            }
                            fmt.Printf("%s: %s (%s)\n", policy.Name, status, policy.ID)
                        }
                    }
                }
            }
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X GET "https://api.gcore.com/waap/v1/domains/${WAAP_DOMAIN_ID}/rule-sets" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          | jq '[.[] | select(.resource_slug == "anti-automation-bot-protection") | .rules[] | select(.id == "S3008869" or .id == "S3008870") | {name, id, mode}]'
        ```

        The response lists both policies with their current state. `mode: true` means enabled; `mode: false` means disabled:

        ```json theme={null}
        [
          {
            "name": "Invalid user agent",
            "id": "S3008869",
            "mode": false
            // ...
          }
          // ...
        ]
        ```
      </Tab>
    </Tabs>

    ## Toggle a policy

    <p>Switch a policy between enabled and disabled. Each call flips the current state. Use the policy ID from the View policy states response or from the table below.</p>

    <Warning>
      This endpoint toggles the current state rather than setting a specific value. If the target state is unknown, retrieve the current policy state first using the View policy states request above.
    </Warning>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import gcore
        import os

        client = gcore.Gcore(api_key=os.environ["GCORE_API_KEY"])
        domain_id = int(os.environ["WAAP_DOMAIN_ID"])

        # S3008869 = Invalid user agent, S3008870 = Unknown user agent
        policy_id = "S3008869"

        result = client.waap.domains.policies.toggle(policy_id, domain_id=domain_id)
        status = "enabled" if result.mode else "disabled"
        print(f"Invalid user agent is now {status}")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"
            "strconv"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/option"
            "github.com/G-Core/gcore-go/waap"
        )

        func main() {
            client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))
            domainID, _ := strconv.ParseInt(os.Getenv("WAAP_DOMAIN_ID"), 10, 64)

            // S3008869 = Invalid user agent, S3008870 = Unknown user agent
            policyID := "S3008869"

            result, _ := client.Waap.Domains.Policies.Toggle(context.Background(), policyID, waap.DomainPolicyToggleParams{DomainID: domainID})
            status := "disabled"
            if result.Mode {
                status = "enabled"
            }
            fmt.Printf("Invalid user agent is now %s\n", status)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        # Set POLICY_ID to S3008869 (Invalid user agent) or S3008870 (Unknown user agent)
        export POLICY_ID="{POLICY_ID}"

        curl -X PATCH "https://api.gcore.com/waap/v1/domains/${WAAP_DOMAIN_ID}/policies/${POLICY_ID}/toggle" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        The API returns the updated policy state. `mode: true` confirms enabled; `mode: false` confirms disabled:

        ```json theme={null}
        {"mode": true}
        ```
      </Tab>
    </Tabs>

    ## Policy reference

    | Policy             | Description                                                                                     | Action    | Default |
    | ------------------ | ----------------------------------------------------------------------------------------------- | --------- | ------- |
    | Invalid user agent | Blocks requests from user agents known to be associated with malicious activity.                | Block     | Enabled |
    | Unknown user agent | Applies a transparent JavaScript-based browser check to requests from unrecognized user agents. | Handshake | Enabled |

    <Info>
      Both policies belong to the [Anti-automation and bot protection](/waap/waap-policies/anti-automation-and-bot-protection) ruleset, which includes six additional policies for managing automated and bot traffic.
    </Info>
  </MethodSection>
</MethodSwitch>
