Skip to main content

DNS filtering rules syntax



Quick links: Download AdGuard Ad Blocker, Get AdGuard Home, Try AdGuard DNS


You can use AdGuard DNS filtering rules syntax to make the rules more flexible, so they can block content according to your preferences. AdGuard DNS filtering rules syntax can be used in different AdGuard products such as AdGuard Home, AdGuard DNS, AdGuard for Windows/Mac/Android.

There are three different approaches to writing hosts blocklists:

  • Adblock-style syntax: the modern approach to writing filtering rules based on using a subset of the Adblock-style rule syntax. This way blocklists are compatible with browser ad blockers.

  • /etc/hosts syntax: the old, tried-and-true approach that uses the same syntax that operating systems do for their hosts files.

  • Domains-only syntax: a simple list of domain names.

If you are creating a blocklist, we recommend using the Adblock-style syntax. It has a couple of important advantages over the old-style syntax:

  • Blocklists size. Using pattern matching allows you to have a single rule instead of hundreds of /etc/hosts entries.

  • Compatibility. Your blocklist will be compatible with browser ad blockers, and it will be easier to share rules with a browser filter list.

  • Extensibility. In the past decade, the Adblock-style syntax has greatly evolved, and we see no reason not to extend it even further and offer additional features for network-level blockers.

If you're maintaining either a /etc/hosts-style blocklist or multiple filtering lists (regardless of type), we provide a tool for blocklist compilation. We named it Hostlist compiler and we use it ourselves to create AdGuard DNS filter.

Basic examples

  • ||^: block access to the domain and all its subdomains, like

  • @@||^: unblock access to the domain and all its subdomains.

  • (attention, old /etc/hosts-style syntax) in AdGuard Home, respond with to queries for the domain but not its subdomains. In Private AdGuard DNS, block access to remains allowed.

    In AdGuard Home, using the unspecified IP address ( or a local address ( and alike) for a host is basically the same as blocking that host.

    # Returns the IP address for
    # Blocks by responding with
  • a simple domain rule. Blocks the domain but not its subdomains. remains allowed.

  • ! Here goes a comment and # Also a comment: comments.

  • /REGEX/: block access to the domains matching the specified regular expression.

Adblock-style syntax

This is a subset of the traditional Adblock-style syntax which is used by browser ad blockers.

     rule = ["@@"] pattern [ "$" modifiers ]
modifiers = [modifier0, modifier1[, ...[, modifierN]]]
  • pattern: the hostname mask. Every hostname is matched against this mask. The pattern can also contain special characters, which are described below.

  • @@: the marker that is used in the exception rules. Start your rule with this marker if you want to turn off filtering for the matching hostnames.

  • modifiers: parameters that clarify the rule. They may limit the scope of the rule or even completely change the way it works.

Special characters

  • *: the wildcard character. It is used to represent any set of characters. This can also be an empty string or a string of any length.

  • ||: matches the beginning of a hostname, including any subdomain. For instance, || matches and but not

  • ^: the separator character. Unlike browser ad blocking, there's nothing to separate in a hostname, so the only purpose of this character is to mark the end of the hostname.

  • |: a pointer to the beginning or the end of the hostname. The value depends on the character placement in the mask. For example, the rule| corresponds to but not to |example corresponds to but not to test.example.

Regular expressions

If you want even more flexibility in making rules, you can use regular expressions instead of the default simplified matching syntax. If you want to use a regular expression, the pattern has to look like this:

pattern = "/" regexp "/"


  • /example.*/ will block hosts matching the example.* regexp.

  • @@/example.*/$important will unblock hosts matching the example.* regexp. Note that this rule also implies the important modifier.


Any line that starts with an exclamation mark or a hash sign is a comment and it will be ignored by the filtering engine. Comments are usually placed above rules and used to describe what a rule does.


! This is a comment.
# This is also a comment.

Rule modifiers

You can change the behavior of a rule by adding modifiers. Modifiers must be located at the end of the rule after the $ character and be separated by commas.


  • ||^ is the matching pattern. $ is the delimiter, which signals that the rest of the rule are modifiers. important is the modifier.

  • You may want to use multiple modifiers in a rule. In that case, separate them by commas:


    ||^ is the matching pattern. $ is the delimiter, which signals that the rest of the rule are modifiers. client= is the client modifier with its value,, is the delimiter. And finally, dnstype=A is the dnstype modifier with its value, A.

NOTE: If a rule contains a modifier not listed in this document, the whole rule must be ignored. This way we avoid false-positives when people are trying to use unmodified browser ad blockers' filter lists like EasyList or EasyPrivacy.


The client modifier allows specifying clients this rule is applied to. There are two main ways to identify a client:

  • By their IP address or CIDR prefix. This way works for all kinds of clients.

  • By their name. This way only works for persistent clients (in AdGuard Home) and devices (in Private AdGuard DNS), which you have manually added.

    NOTE: In AdGuard Home, ClientIDs are not currently supported, only names are. If you have added a client with the name “My Client” and ClientID my-client spell your modifier as $client='My Client' as opposed to $client=my-client.

The syntax is:


You can also exclude clients by adding a ~ character before the value. In this case, the rule is not be applied to this client's DNS requests.


Client names usually contain spaces or other special characters, which is why you should enclose the name in quotes. Both single and double ASCII quotes are supported. Use the backslash (\) to escape quotes (" and '), commas (,), and pipes (|).

NOTE: When excluding a client, you must place ~ outside the quotes.


  • @@||*^$client= unblock everything for localhost.

  • ||^$client='Frank\'s laptop': block for the client named Frank's laptop only. Note that quote (') in the name must be escaped.

  • ||^$client=~'Mary\'s\, John\'s\, and Boris\'s laptops': block for everyone except for the client named Mary's, John's, and Boris's laptops. Note that comma (,) must be escaped as well.

  • ||^$client=~Mom|~Dad|Kids: block for Kids, but not for Mom and Dad. This example demonstrates how to specify multiple clients in one rule.

  • ||^$client= block for all clients with IP addresses in the range from to


You can use the denyallow modifier to exclude domains from the blocking rule. To add multiple domains to one rule, use the | character as a separator.

The syntax is:


This modifier allows avoiding creating unnecessary exception rules when our blocking rule covers too many domains. You may want to block everything except for a couple of TLD domains. You could use the standard approach, i.e. rules like this:

! Block everything.

! Unblock a couple of TLDs.

The problem with this approach is that this way you will also unblock tracking domains that are located on those TLDs (i.e. Here's how to solve this with denyallow:



  • *$denyallow=com|net: block everything except for *.com and *.net.

  • @@*$denyallow=com|net: unblock everything except for *.com and *.net.

  • ||^$ block and * but don't block


The dnstype modifier allows specifying DNS request or response type on which this rule will be triggered.

The syntax is:


The names of the types are case-insensitive, but are validated against a set of actual DNS resource record (RR) types.

Do not combine exclusion rules with inclusion ones. This:


is equivalent to this:



  • ||^$dnstype=AAAA: block DNS queries for the IPv6 addresses of

  • ||^$dnstype=~A|~CNAME: only allow A and CNAME DNS queries for, block out the rest.

NOTE: Before version v0.108.0, AdGuard Home would use the type of the request to filter the response records, as opposed to the type of the response record itself. That caused issues, since that meant that you could not write rules that would allow certain CNAME records in responses in A and AAAA requests. In v0.108.0 that behaviour was changed, so now this:


allows you to avoid filtering of the following response:

canonical name =
ttl = 60
internet address =
ttl = 60


The dnsrewrite response modifier allows replacing the content of the response to the DNS request for the matching hosts. Note that this modifier in AdGuard Home works in all rules, but in Private AdGuard DNS — only in custom ones.

Rules with the dnsrewrite response modifier have higher priority than other rules in AdGuard Home.

The shorthand syntax is:


The keywords MUST be in all caps (e.g. NOERROR). Keyword rewrites take precedence over the other and will result in an empty response with an appropriate response code.

The full syntax is of the form RCODE;RRTYPE;VALUE:


The $dnsrewrite modifier with the NOERROR response code may also has empty RRTYPE and VALUE fields.

The CNAME one is special because AdGuard Home will resolve the host and add its info to the response. That is, if has IP, and the user has this in their filter rules:

! Or:

then the response will be something like:

nslookup my.adguard.local
Server: my.adguard.local

Non-authoritative answer: canonical name =

Next, the CNAME rewrite. After that, all other records' values are summed as one response, so this:


will result in a response with two A records.

Currently supported RR types with examples:

  • ||^$dnsrewrite=NOERROR;PTR; adds a PTR record for reverse DNS. Reverse DNS requests for to the DNS server will result in

    NOTE: the IP MUST be in reverse order. See RFC 1035.

  • ||^$dnsrewrite=NOERROR;A; adds an A record with the value

  • ||^$dnsrewrite=NOERROR;AAAA;abcd::1234 adds an AAAA record with the value abcd::1234.

  • ||^$dnsrewrite=NOERROR;CNAME; adds a CNAME record. See explanation above.

  • ||^$dnsrewrite=NOERROR;HTTPS;32 alpn=h3 adds an HTTPS record. Only a subset of parameter values is supported: values must be contiguous and, where a value-list is expected, only one value is currently supported:

    ipv4hint=             // Supported.
    ipv4hint="" // Unsupported.
    ipv4hint=, // Unsupported.
    ipv4hint="," // Unsupported.

    This will be changed in the future.

  • ||^$dnsrewrite=NOERROR;MX;32 example.mail adds an MX record with precedence value 32 and exchange value example.mail.

  • ||^$dnsrewrite=NOERROR;SVCB;32 alpn=h3 adds a SVCB value. See the HTTPS example above.

  • ||^$dnsrewrite=NOERROR;TXT;hello_world adds a TXT record with the value hello_world.

  • ||^$dnsrewrite=NOERROR;SRV;10 60 8080 adds an SRV record with priority value 10, weight value 60, port8080, and target value

  • ||^$dnsrewrite=NXDOMAIN;; responds with an NXDOMAIN code.

  • $dnstype=AAAA,,dnsrewrite=NOERROR;; responds with an empty NOERROR answers for all AAAA requests except the ones for

Exception rules unblock one or all rules:

  • @@||^$dnsrewrite unblocks all DNS rewrite rules.

  • @@||^$dnsrewrite= unblocks the DNS rewrite rule that adds an A record with the value


The important modifier applied to a rule increases its priority over any other rule without the modifier. Even over basic exception rules.


  • In this example:


    ||^$important will block all requests to * despite the exception rule.

  • In this example:


    the exception rule also has the important modifier, so it will work.


The rules with the badfilter modifier disable other basic rules to which they refer. It means that the text of the disabled rule should match the text of the badfilter rule (without the badfilter modifier).


  • ||$badfilter disables ||

  • @@||^$badfilter disables @@||^.

    NOTE: The badfilter modifier currently doesn't work with /etc/hosts-style rules.$badfilter will not disable the original rule.


The ctag modifier can only be used in AdGuard Home.

It allows to block domains only for specific types of DNS client tags. You can assign tags to clients in the AdGuard Home UI. In the future, we plan to assign tags automatically by analyzing the behavior of each client.

The syntax is:


If one of client's tags matches the ctag values, this rule applies to the client. The syntax for exclusion is:


If one of client's tags matches the exclusion ctag values, this rule doesn't apply to the client.


  • ||^$ctag=device_pc|device_phone: block for clients tagged as device_pc or device_phone.

  • ||^$ctag=~device_phone: block for all clients except those tagged as device_phone.

The list of allowed tags:

  • By device type:

    • device_audio: audio devices.
    • device_camera: cameras.
    • device_gameconsole: game consoles.
    • device_laptop: laptops.
    • device_nas: NAS (Network-attached Storages).
    • device_pc: PCs.
    • device_phone: phones.
    • device_printer: printers.
    • device_securityalarm: security alarms.
    • device_tablet: tablets.
    • device_tv: TVs.
    • device_other: other devices.
  • By operating system:

    • os_android: Android.
    • os_ios: iOS.
    • os_linux: Linux.
    • os_macos: macOS.
    • os_windows: Windows.
    • os_other: other OSes.
  • By user group:

    • user_admin: administrators.
    • user_regular: regular users.
    • user_child: children.

/etc/hosts-style syntax

For each host a single line should be present with the following information:

IP_address canonical_hostname [aliases...]

Fields of the entries are separated by any number of space or tab characters. Text from the # character until the end of the line is a comment and is ignored.

Hostnames may contain only alphanumeric characters, hyphen-minus signs (-), and periods (.). They must begin with an alphabetic character and end with an alphanumeric character. Optional aliases provide for name changes, alternate spellings, shorter hostnames, or generic hostnames (for example, localhost).


# This is a comment # this is also a comment

In AdGuard Home, the IP addresses are used to respond to DNS queries for these domains. In Private AdGuard DNS, these addresses are simply blocked.

Domains-only syntax

A simple list of domain names, one name per line.


# This is a comment # this is also a comment

If a string is not a valid domain (e.g. *, AdGuard Home will consider it to be an Adblock-style syntax rule.

Hostlist compiler

If you are maintaining a blocklist and use different sources in it, Hostlist compiler may be useful to you. It is a simple tool that makes it easier to compile a hosts blocklist compatible with AdGuard Home, Private AdGuard DNS or any other AdGuard product with DNS filtering.

What it's capable of:

  1. Compile a single blocklist from multiple sources.

  2. Exclude the rules you don't need.

  3. Cleanup the resulting list: deduplicate, remove invalid rules, and compress the list.