---
title: "How to block ads and trackers in one browser profile"
description: "Block ads and trackers in one Donut Browser profile with a DNS blocklist, a custom list or a filtering DNS resolver, and fix the sites that break."
url: "https://donutbrowser.com/docs/guides/block-ads-in-one-profile/"
---

# How to block ads and trackers in one browser profile

A system-wide ad blocker or a filtering DNS server changes every browser and app on your computer. Donut Browser filters per profile: one profile can block ads, trackers and malware domains while another loads everything. The filter works with a proxy, with a VPN and with no proxy at all, and it needs no extension. You need Donut Browser [installed](https://donutbrowser.com/docs/install).

## How the blocklist works

Each profile reaches the internet through a small Donut relay on your computer. With a blocklist on, the relay refuses a connection to a listed domain and to all of its subdomains before any lookup. The browser shows its own connection error for that request, and the page loads without it. No query for a blocked name leaves your computer.

The lists are the HaGeZi DNS blocklists. Donut downloads a list the first time a profile needs it, then refreshes the lists every 12 hours.

| Level | Source |
| --- | --- |
| None | No filtering |
| Light | HaGeZi Light |
| Normal | HaGeZi Multi Normal |
| Pro | HaGeZi Multi Pro |
| Pro++ | HaGeZi Multi Pro++ |
| Ultimate | HaGeZi Multi Ultimate |
| Custom | Your own sources and rules |

Each level from Light to Ultimate blocks more domains than the one before it, and a longer list breaks more sites. The domain count of each list is in the blocklist dialog (step 2).

## 1. Choose a level for the profile

Use one of these. The level applies from the next launch, so restart a running profile.

- In the profile table, click the profile's **DNS** cell and choose a level.
- In **Create new profile**, open **Advanced options** and set **DNS blocklist**.
- For several profiles, select them and click **Edit selected** in the action bar. The **Edit profiles** dialog has a **DNS blocklist** field.

Ephemeral profiles can use a blocklist too.

## 2. Launch and test

Launch the profile and open a page with ads. Then open the same page in a profile with the level **None** and compare. If the list was not downloaded yet, the launch waits for it.

To see the lists, open **Settings** → **DNS blocklist** → "Block ads, trackers and malware" → **Manage**. The **Blocklists** tab shows each level with its badge (**Fresh**, **Stale** or **Not cached**), its domain count, size and date. **Refresh All Lists** downloads them again.

## 3. Build a custom list

The **Custom lists** tab in the same dialog builds one list that every profile with the level **Custom** uses.

| Field | What goes in it |
| --- | --- |
| Blocklist source URLs | One URL per line, for lists you want to merge in |
| Blocked domains | One domain per line |
| Allowed domains | Domains to take out of the compiled list. They win over every block rule. |
| Allowlist mode | When on, only the domains in **Allowed domains (only these)** load, with their subdomains. Everything else is blocked. An empty list turns filtering off. |

Click **Save** to compile the list. **Import** reads a `.json` or `.txt` file, and **Export TXT** and **Export JSON** write one.

Each line can be a plain domain (`ads.example.com`), a hosts-file line with `0.0.0.0`, `127.0.0.1`, `::` or `::1`, a wildcard (`*.ads.example.com`), or an adblock-style rule (`||ads.example.com^`). Lines that start with `#` or `!` are comments.

Use domain lists only. Browser filter lists with element-hiding rules, such as `example.com##.banner`, do not work here: Donut cuts such a line at the `#`, and the rule then blocks all of `example.com`. Exception rules (`@@`) and rules with `$` options in a source list are not understood either.

Allowlist mode suits a profile that must reach a few sites only, such as one web app for one account.

## Another way: a filtering DNS server

Some public DNS servers return no answer for ad and tracker domains. Donut can send a profile's DNS queries to one of them, through the profile's proxy or VPN:

1. Stop the profile and open its panel → **Network**.
2. In the **DNS** field, enter a DNS over HTTPS address such as `https://adblock.dns.mullvad.net/dns-query`, and save it.

When the server answers "no such domain", Donut tells the browser the host is unreachable. You can use this together with a blocklist. If the DNS server does not answer, pages in the profile do not load.

## Set the level with the API

`PUT /v1/profiles/{id}` has no blocklist field. Use the bulk editor route, which takes one or many profiles and works on every plan:

```bash
curl -sS -X POST http://127.0.0.1:10108/v1/profiles/bulk-edit \
  -H "Authorization: Bearer $DONUT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"profile_ids": ["<profile id>"], "patch": {"dns_blocklist": "pro"}}'
# {"changed":1}
```

```javascript
const res = await fetch("http://127.0.0.1:10108/v1/profiles/bulk-edit", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.DONUT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    profile_ids: [profileId],
    patch: { dns_blocklist: "pro" },
  }),
});
console.log(res.status, await res.json());
```

```python
import os, requests

response = requests.post(
    "http://127.0.0.1:10108/v1/profiles/bulk-edit",
    headers={"Authorization": f"Bearer {os.environ['DONUT_API_KEY']}"},
    json={"profile_ids": [profile_id], "patch": {"dns_blocklist": "pro"}},
    timeout=10,
)
print(response.status_code, response.json())
```

The values are `none`, `light`, `normal`, `pro`, `pro_plus`, `ultimate` and `custom`. `"none"` or `null` turns the filter off. An unknown value returns `400` with `DNS_BLOCKLIST_INVALID`, and a running profile returns `409`; in both cases nothing changes. Templates take the same value in `settings.dns_blocklist`, and an AI agent can use the MCP tool `update_profile_dns_blocklist`. See [Bulk-edit profiles](https://donutbrowser.com/docs/rest-api#bulk-edit-profiles).

## What a DNS blocklist cannot do

A blocklist works on whole domains. It cannot hide an empty ad box, and it cannot block an ad that a site serves from its own domain, such as a video ad on the site's own servers. For that, add a content-blocking extension to the profile. See [Extensions](https://donutbrowser.com/docs/extensions).

Blocked requests do not show in **Traffic Details**, and Donut keeps no count of them.

## Troubleshooting

| Problem | What to do |
| --- | --- |
| A site breaks or a button does nothing | Lower the level, or switch the profile to **Custom** and add the domain to **Allowed domains**. |
| An allowed domain is still blocked | Allowed domains match exactly. If `example.com` is on the list, allowing `cdn.example.com` does not free it. Allow the listed parent domain. |
| The launch fails with "Failed to fetch DNS blocklist" | Donut could not download the list. Check your connection, or choose another level. |
| A level change does nothing | The profile was running. Stop it and launch it again. |
| Pages do not load after you set a DNS server | The server does not answer through the profile's route. Clear the profile's **DNS** field. |

## Related

- [DNS and DNS blocklist](https://donutbrowser.com/docs/proxies#dns-blocklist): the settings in the app.
- [How to use a SOCKS5 proxy with a username and password](https://donutbrowser.com/docs/guides/socks5-proxy-with-password)
- [How to create many browser profiles, each with its own proxy](https://donutbrowser.com/docs/guides/bulk-create-profiles)

DNS blocklists are part of the free plan, for every profile. [Download Donut Browser](https://donutbrowser.com/) for macOS, Windows or Linux.
