---
name: azion-deny-requests-from-a-list-of-countries
description: >-
  Create a countries network list and a firewall rule that denies each request from those countries, in Azion Console, the Azion CLI, or the API.
---

# Deny requests from a list of countries

You can deny every client in a list of countries from Azion Console, the [Azion CLI](/en/documentation/devtools/cli/), or the API. A `countries` [network list](/en/documentation/platform/firewall/network-shield/network-lists/) names the countries. One [firewall](/en/documentation/platform/firewall/) rule denies each client that Azion places in one of them. Use it when your application serves no one in those countries. Their requests then end at the firewall with `403`. To deny one network instead of a whole country, refer to [Deny requests from one autonomous system](/en/documentation/guides/application-security/bots-and-network/deny-asn/).

---

Select the interface you will use. The prerequisites and each task on this page follow that choice.

## Prerequisites

- A [workload](/en/documentation/platform/workloads/) bound to a firewall, which carries the rule in this guide.
- [Network Shield](/en/documentation/platform/firewall/#network-shield) on for that firewall. A firewall is created with Network Shield on unless you turn it off.

**Console**

- Access to [Azion Console](https://console.azion.com/).

**CLI**

- The Azion CLI, installed and configured with a [personal token](/en/documentation/fundamentals/personal-tokens/).
- The ID of the firewall bound to your workload.

**API**

- A [personal token](/en/documentation/fundamentals/personal-tokens/), which replaces `[TOKEN VALUE]` in each request.
- The ID of the firewall bound to your workload.

---

## Create the countries list

A `countries` list holds one item per country: its uppercase ISO 3166-1 alpha-2 code, such as `BR` or `US`. Azion Console selects each country by name and sends its code. The API refuses a lowercase code or a name, such as `br` or `Brazil`, with `22015 Invalid Country`. The list keeps the `countries` type for as long as it exists. An item takes no due date and no comment. A country therefore stays denied until a write of the list's items leaves it out. For every field and type of a list, refer to [Network list fields](/en/documentation/platform/firewall/network-shield/network-lists/#network-list-fields) and [List types](/en/documentation/platform/firewall/network-shield/network-lists/#list-types).

**Console**

To create the list in Azion Console:

1. **Open the Network Lists page**

   Access [Azion Console](https://console.azion.com/) > **Edge Libraries** > **Network Lists**.

2. **Select Network List**

3. **Name the list**

   In the **General** section, enter a **Name**. For example: `Blocked countries`.

4. **Select the Countries type**

   In the **Network List Settings** section, select *Countries*. The form opens with *ASN* selected.

5. **Select the countries to deny**

   In the **Countries** field, select each country by its name.

6. **Save the list**

   Select **Save**.

Azion Console shows the message `Your network list has been created`. **Network Lists** then shows the list, with *Countries* in its **List Type** column.

**CLI**

To create the list with the Azion CLI, pass the codes to `--items`, separated by commas:

```bash
azion create network-list --name "Blocked countries" --type countries --items "BR,US"
```

The CLI answers with the list's ID:

```text
Created Network List with ID <network-list-id>
```

The list `Blocked countries` exists, and the rule names it by that ID.

**API**

To create the list with the API, send a `POST` request to `/v4/workspace/network_lists`. Replace `[TOKEN VALUE]` with your personal token:

```bash
curl -X POST https://api.azion.com/v4/workspace/network_lists \
  -H "Authorization: Token [TOKEN VALUE]" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name":"Blocked countries","type":"countries","items":["BR"]}'
```

The API answers `201`, and a `state` of `executed` means the list is already stored. This excerpt of the response keeps the fields the rule reads:

```json
{
  "state": "executed",
  "data": {
    "id": <network-list-id>,
    "name": "Blocked countries",
    "type": "countries",
    "items": ["BR"],
    ...
    "active": true,
    ...
  }
}
```

The list exists, and `data.id` is the ID that the rule names. To deny more countries, send one code per country in the same `items` array.

---

## Create the rule that denies the list

The rule compares each request's client address with the `countries` list through the *Network* criterion. Its *Deny (403 Forbidden)* behavior refuses every match. The rule stores the ID of the list, not the countries in it. A country you add to the list or remove from it changes what the rule denies, with no edit to the rule. For every criterion and behavior a rule accepts, refer to [Rules Engine for Firewall](/en/documentation/platform/firewall/rules-engine/#criteria).

**Console**

To create the rule in Azion Console:

1. **Open the firewall bound to your workload**

   Access [Azion Console](https://console.azion.com/) > **Secure** > **Firewalls**, and select the firewall.

2. **Select the Rules Engine tab**

3. **Select Rule**

   The **Create Rule** drawer opens.

4. **Name the rule**

   In the **General** section, enter a **Name**. For example: `Deny listed countries`.

5. **Set the Network criterion**

   In the **Criteria** section, select the *Network* variable and the *matches* operator.

   If the variable reads *Network - required Network Shield*, Network Shield is off for this firewall. Turn on **Network Shield** in **Main Settings** > **Modules** and save, and the variable becomes selectable.

6. **Select the list**

   In the **Select a Network** dropdown, select `Blocked countries`.

7. **Add the Deny behavior**

   In the **Behaviors** section, select *Deny (403 Forbidden)*.

8. **Save the rule**

   Select **Save**.

Azion Console shows the message `Rule successfully created`. The **Rules Engine** tab lists the rule, with *Active* in its **Status** column.

**CLI**

To create the rule with the Azion CLI, save it as `rule.json`. Write the ID of your list in place of `<network-list-id>`, as a number without quotes:

```json
{
  "name": "Deny listed countries",
  "active": true,
  "criteria": [
    [
      { "variable": "${network}", "conditional": "if", "operator": "is_in_list", "argument": <network-list-id> }
    ]
  ],
  "behaviors": [
    { "type": "deny" }
  ]
}
```

Then create the rule from the file. Put the ID of the firewall bound to your workload in place of `<firewall-id>`:

```bash
azion create firewall-rule --firewall-id <firewall-id> --file rule.json
```

The CLI answers with the rule's ID:

```text
Created Firewall Rule with ID <rule-id>
```

The firewall holds the rule, active, and the rule denies every country in `Blocked countries`.

**API**

To create the rule with the API, send a `POST` request to `/v4/workspace/firewalls/{firewall_id}/request_rules`. Put the ID of the firewall bound to your workload in place of `<firewall-id>`. In place of `<network-list-id>`, write `data.id` from the list response as a number, without quotes:

```bash
curl -X POST https://api.azion.com/v4/workspace/firewalls/<firewall-id>/request_rules \
  -H "Authorization: Token [TOKEN VALUE]" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Deny listed countries",
  "active": true,
  "criteria": [
    [
      { "variable": "${network}", "conditional": "if", "operator": "is_in_list", "argument": <network-list-id> }
    ]
  ],
  "behaviors": [
    { "type": "deny" }
  ]
}'
```

The API answers `202` and returns the rule as stored:

```json
{
  "state": "pending",
  "data": {
    "id": <rule-id>,
    "name": "Deny listed countries",
    "active": true,
    "criteria": [[{ "conditional": "if", "variable": "${network}", "operator": "is_in_list", "argument": <network-list-id> }]],
    "behaviors": [{ "type": "deny" }],
    "description": "",
    "order": 0
  }
}
```

The firewall holds the rule. The platform adds an empty `description` and an `order`. `order` is the position of the rule among the firewall's rules, counted from `0`.

> **Note**
>
> In the JSON of the CLI and the API, `criteria` holds one block with one criterion, whose `conditional` is `if`. `${network}` is the *Network* criterion, `is_in_list` its *matches* operator, and `deny` the *Deny (403 Forbidden)* behavior. With Network Shield off, the rule is refused with `25047 Missing Required Modules`. The list ID in quotes is refused with `25042 Invalid Operator Argument Type`. For every operator and error of this criterion, refer to [The Network criterion](/en/documentation/platform/firewall/network-shield/network-lists/#the-network-criterion).

---

## Confirm that the rule denies a listed country

The rule in this guide has no criterion besides *Network*, so it denies clients in the listed countries on every path of the workload. Their requests end at the firewall, and the application never receives them. A rule you create can take 6 minutes 29 seconds to 9 minutes 18 seconds to reach traffic across Azion's distributed infrastructure. Until it does, those clients still reach the application.

Once the rule reaches traffic, a client that Azion places in a listed country receives `HTTP 403`. The answer carries Azion's default error page, headed **Forbidden**. For example, a list that holds `BR` denies a client in Brazil. A denied request receives this response:

```text
$ curl -i https://<your-workload-domain>/
HTTP/2 403
server: nginx
date: Thu, 01 Jan 2026 12:00:00 GMT
content-type: text/html; charset=utf-8
x-content-type-options: nosniff
x-azion-request-id: <request-id>
x-azion-edge-location: <edge-location>
alt-svc: h3=":443"; ma=86400

<title>Azion - Default error page</title>
...
<h1 class="error-header__title">Forbidden</h1>
...
Your IP         <your-ip>
Request ID      <request-id>
Status Code     403
Edge Location   <edge-location>
```

The `Your IP` row shows the address that Azion placed in a listed country. A later change to the countries in the list can take 46 seconds to about 100 seconds to reach traffic. In that window, answers can alternate between the old countries and the updated ones. Repeat the request until the answers agree. For what a denied client receives, refer to [Deny (403 Forbidden)](/en/documentation/platform/firewall/rules-engine/#deny-403-forbidden).

Azion takes the country of an address from databases that external suppliers provide. That country can be wrong for some addresses. The Azion [Terms of Service](/en/documentation/agreements/tos/) state that access control by country is applied on a best-effort basis. The same terms name restriction by IP address as the way to obtain the best level of control.

A *Request Uri* criterion limits the rule to one path. To try the rule on one path before it covers the whole workload, refer to [Guard one path with a network list](/en/documentation/guides/application-security/bots-and-network/guard-one-path/).

---

## Next steps

- [Guard one path with a network list](/en/documentation/guides/application-security/bots-and-network/guard-one-path.md): Limit the same deny rule to one path with a second criterion, and leave every other path open.
- [Network Lists](/en/documentation/platform/firewall/network-shield/network-lists.md): Every list field and type, and each error that a list or a Network criterion returns.
- [How Firewall works](/en/documentation/platform/firewall/how-it-works.md#network-shield): Its Network Shield section explains how a list matches a client address, and how one list serves many rules.
- [Firewall guides and tutorials](/en/documentation/platform/firewall/guides.md): The other configurations built on network lists, and every other guide for a firewall.
