How to create your own ad filters

Introduction

A filter is a set of filtering rules applied to specific content (banners, popups, etc). AdGuard has a list of standard filters created by our team. Our team constantly improves and updates them, and we hope our filters meet the needs of most of our users.

At the same time, AdGuard allows you to create your own custom filters, using the same type of rules that we have in our filters.

To describe the syntax of our filtering rules we use Augmented BNF for Syntax Specifications, but we do not always strictly follow this specification.

AdGuard syntax is originally based on syntax of Adblock Plus rules, but it was extended with new types of rules for better ad filtering. Some parts of this article's content about the rules common to both AdGuard and ABP was taken from this article.

Comments

Any line that starts with an exclamation mark is a comment. In the list of rules it is displayed in gray color. AdGuard will ignore this line, so you can write anything you want. Comments are usually placed above the rules and used to describe what a rule does.

For example:

! This is the comment. Under this line there is an actual filtering rule.
||example.org^

Examples

Example: Blocking by domain name

This rule blocks:

  • http://example.org/ad1.gif
  • http://subdomain.example.org/ad1.gif
  • https://ads.example.org:8000/

This rule does not block:

  • http://ads.example.org.us/ad1.gif
  • http://example.org/redirect/http://ads.example.org/

Example: Blocking exact address

This rule blocks:

  • http://example.org/

This rule does not block:

  • https://example.org/banner/img

Example: Basic rule modifiers

Filtering rules support numerous modifiers that allow you to fine-tune the rule behavior. Here is an example of a rule with some simple modifiers.

This rule blocks:

  • http://example.org/script.js if this script is loaded from example.com.

This rule does not block:

  • https://example.org/script.js if this script is loaded from example.org.
  • https://example.org/banner.png because it is not a script.

Example: Unblocking an address

This rule unblocks:

  • http://example.org/banner.png even if there is a blocking rule for this address.

Blocking rules with $important modifier can override exceptions.

Unblocking everything on a website

This rule unblocks

  • It disables all cosmetic rules on example.com.
  • It unblocks all requests sent from this website even if there is are blocking rules matching these requests.

Example: Cosmetic rule

Cosmetic rules are based on using a special language named CSS, which every browser understands. Basically, it adds a new CSS style to the website which purpose is to hide particular elements. You can learn more about CSS in general here.

AdGuard extends CSS and lets filters developers handle much more complicated cases. However, to use these extended rules, you need to be fluent in regular CSS.

Name CSS selector Description
ID selector #banners Matches all elements with id attribute equal to banners.
Class selector .banners Matches all elements with class attribute containing banners.
Attribute selector div[class="banners"] Matches all div elements with class attribute exactly equal to banners.
Attribute substring selector div[class^="advert1"] Matches all div elements which class attribute starts with the advert1 string.
Attribute substring selector div[class$="banners_ads"] Matches all div elements which class attribute ends with the banners_ads string.
Attribute substring selector a[href^="http://example.com/"] Matches all links that are loaded from http://example.com/ domain.
Attribute selector a[href="http://example.com/"] Matches all links to exactly the http://example.com/ address.

Basic rules

The most simple rules are so-called "Basic rules". They are used to block requests to specific URLs. Or to unblock it, if there is a special marker "@@" at the beginning of the rule. The basic principle for this type of rules is quite simple: you have to specify the address and additional parameters that limit or expand the scope of the rule.

Sub-requests

Basic rules for blocking requests are applied only to sub-requests. That means they will not block the loading of the page.

Response status

Browser detects a blocked request as completed with an error.

Basic rules syntax

      rule = ["@@"] pattern [ "$" modifiers ]
modifiers = [modifier0, modifier1[, ...[, modifierN]]]
  • pattern — address mask. Every request's URL is collated to this mask. You can also use special characters in the template, their description is below.
  • @@ — A marker that is used in rules of exception. To turn off filtering for a request, start your rule with this marker.
  • modifiers — Parameters that "clarify" the basic rule. Some of them limit the scope of the rule and some can completely change they way it works.

Special characters

  • * — Wildcard character. It is used to represent "any set of characters". This can also be an empty string or a string of any length.
  • || — Matching the beginning of an address. With this character you don't have to specify a particular protocol and subdomain in address mask. It means, || stands for http://*., https://*., ws://*., wss://*. at once.
  • ^ — Separator character mark. Separator character is any character, but a letter, a digit, or one of the following: _ - . %. In this example separator characters are shown in bold: http://example.com/?t=1&t2=t3. The end of the address is also accepted as separator.
  • | — A pointer to the beginning or the end of address. The value depends on the character placement in the mask. For example, a rule swf| corresponds to http://example.com/annoyingflash.swf , but not to http://example.com/swf/index.html. |http://example.org corresponds to http://example.org, but not to http://domain.com?url=http://example.org.

Visual representation

We recommend to get acquainted with this article, for better understanding of how such rules should be made.

Regular expressions support

If you want even more flexibility in making rules, you can use Regular expressions instead of a default simplified mask with special characters.

Performance

Rules with regular expressions work more slowly, therefore it is recommended to avoid them or to limit their scope to specific domains.

If you want a blocker to determine a regular expression, the pattern has to look like this:

pattern = "/" regexp "/"

For example, /banner\d+/$third-party this rule will apply the regular expression banner\d+ to all third-party requests. Exclusion rule with regular expression looks like this: @@/banner\d+/.

Compatibility with different versions of AdGuard

AdGuard browser extension for Safari and AdGuard for iOS do not fully support regular expressions because of Content Blocking API restrictions (look for "The Regular expression format" section).

Basic rules examples

  • ||example.com/ads/* — a simple rule, which corresponds to addresses like http://example.com/ads/banner.jpg and even http://subdomain.example.com/ads/otherbanner.jpg.

  • ||example.org^$third-party — a rule that blocks third-party requests toexample.org and it's subdomains.

  • @@||example.com$document — general exception rule. It completely disables filtering for example.com and all subdomains. There is a number of modifiers which can be used in exception rules. For more details, please follow the link below.

Modifiers

Attention

The features described in this section are intended for experienced users. They extend capabilities of "Basic rules", but in order to use them you need to have a basic undestanding of the way your browser works.

You can change the behavior of a "basic rule" by using additional modifiers. Modifiers should be located in the end of the rule after a $ sign and be separated by commas.

Example:

||domain.com^$popup,third-party

Basic modifiers

The following modifiers are the most simple and frequently used.

domain

domain limits the rule application area to a list of domains (and their subdomains). To add multiple domains to one rule, use the | character as a separator.

domain examples
  • ||baddomain.com^$domain=example.org — a rule to block requests that match the specified mask, and are sent from domain example.org or it's subdomains.
  • ||baddomain.com^$domain=example.org|example.com — the same rule, but it works for both example.org and example.com.

If you want the rule not to be applied to certain domains, start a domain name with ~ sign.

domain and ~ examples
  • ||baddomain.com^$domain=~example.org — a rule to block requests that match the specified mask, and are sent from any domain except example.org or it's subdomains.
  • ||baddomain.com^$domain=example.org|~foo.example.org — this rule blocks requests that are sent from example.org and all it's subdomains, except the subdomain foo.example.org.

third-party

A restriction of third-party and own requests. A third-party request is a request from different domain. For example, a request to example.org, from domain.com is a third-party request.

Subdomains

Please note that request from domain to it's subdomain (or vice versa) is not considered a third-party request. For example, a request to subdomain.example.org, sent from the domainexample.org is not a third-party request.

If there is a third-party modifier, the rule is only applied to third-party request.

third-party examples
  • ||domain.com^$third-party — rule is applied to all domains, except domain.com and it's subdomains. Third-party request example: http://example.org/banner.jpg.

If there is a ~third-party modifier, the rule is only applied to the requests that are not from third-party. Which means, they have to be sent from the same domain.

~third-party examples
  • ||domain.com$~third-party — this rule is applied to domain.com, but not to the other domains. Example of a request that is not a third-party request: http://domain.com/icon.ico.

AdGuard will try to close the browser tab with any address that matches a blocking rule with this modifier. Please note, that not all the tabs can be closed.

popupexamples
  • ||domain.com^$popup — if you try to go to http://domain.com/ from any page in the browser, a new tab in which specified site has to be opened will be closed by this rule.

match-case

This modifier defines a rule which applies only to addresses that match the case. Default rules are case-insensitive.

match-case examples
  • */BannerAd.gif$match-case — this rule will block http://example.com/BannerAd.gif, but not http://example.com/bannerad.gif.

Restriction by content type

There is a set of modifiers, which can be used to limit the rule's application area to certain type of content. These modifiers can also be combined to cover, for example, both images and scripts.

Compatibility with different versions of AdGuard

Please note that there is a big difference in how AdGuard determines the content type on different platforms. For browser extensions, content type for every request is provided by browser. AdGuard for Windows, Mac and Android use following method: first we try to determine the type of request by filename extension. If the request is not blocked at this stage, the type will be determined using the Content-Type header at the beginning of the server response.

Content type modifiers examples
  • ||example.org^$image — corresponds to all images from example.org.
  • ||example.org^$script,stylesheet — corresponds to all the scripts and styles from example.org.
  • ||example.org^$~image,~script,~stylesheet — corresponds to all requests to example.org except for the images, scripts and styles.

image

The rule corresponds to images requests.

stylesheet

The rule corresponds to CSS files requests.

script

The rule corresponds to script requests (e.g. javascript, vbscript).

object

The rule corresponds to browser plugins resourses. (e.g. Java or Flash).

object-subrequest

The rule corresponds to requests by browser plugins (it's usually Flash).

Compatibility with different versions of AdGuard

AdGuard for Windows, macOS and Android often can't accurately determine this type and defines it as other.

font

The rule corresponds to requests for fonts (e.g. .woff filename extension).

media

The rule corresponds to requests for media files (music and video, e.g. .mp4 files).

subdocument

The rule corresponds to requests for built-in pages (HTML tags frame and iframe).

xmlhttprequest

The rule applies only to ajax requests (requests sent via javascript object XMLHttpRequest).

Compatibility with different versions of AdGuard

AdGuard for Windows, macOS and Android often can't accurately determine this type and defines it as other or script.

websocket

The rule applies only to WebSocket connections.

other

The rule applies to requests for which the type has not been determined or doesn't match the types listed above.

Exception modifiers

Exception rules disable the other basic rules for the addresses to which they correspond. They begin with a @@ mark. All the basic modifiers listed above can be applied to them and they also have a few special modifiers.

Visual representation

We recommend to get acquainted with this article, for better understanding of how exception rules should be made.

elemhide

Disables any cosmetic rules on the pages matching the rule. You will find the information about cosmetic rules further.

elemhide example
  • @@||example.com^$elemhide — disables all cosmetic rules on pages at example.com and all subdomains.

content

Disables HTML filtering rules on the pages matching the rule. You will find the information about HTML filtering rules further.

content example
  • @@||example.com^$content — disables all HTML filtering rules on pages at example.com and all subdomains.

jsinject

Forbids adding of javascript code to the page. You can read about javascript rules further.

jsinject example
  • @@||example.com^$jsinject — disables javascript on pages at example.com and all subdomains.

urlblock

Disables blocking of all requests sent from the pages matching the rule.

urlblock example
  • @@||example.com^$urlblock — any requests sent from the pages at example.com and all subdomains are not going to be blocked.

extension

Disables all userscripts on the pages matching this rule.

extension example
  • @@||example.com^$extension — userscripts won't work on all pages of the example.com website.

document

Completely disables blocking on corresponding pages. It is equal to simultaneous use of elemhide, content, urlblock, jsinject and extension.

document example
  • @@||example.com^$document — completely disables filtering on all pages at example.com and all subdomains.
  • @@||example.com^$document,~extension — completely disables blocking on any pages at example.com and all subdomains, but continues to run userscripts there.

stealth

Disables the Stealth Mode for all corresponding pages and requests.

Compatibility with different versions of AdGuard

Stealth Mode is currently available only in AdGuard for Windows. We plan to add it to all our products in future. For now, the products that do not support Stealth Mode will ignore the rules with this modifier.

stealth example
  • @@||example.com^$stealth — disables Stealth Mode for all pages at example.com and all subdomains, and also for all requests and sub-requests.

Generic rules

Before we can proceed to the next modifiers, we have to make a definition of generic rules. The rule is generic if it is not limited to specific domains.

For example, these rules are generic:

###banner
~domain.com###banner
||domain.com^
||domain.com^$domain=~example.com

And these are not:

domain.com###banner
||domain.com^$domain=example.com

generichide

Disables all generic cosmetic rules on pages that correspond to exception rule.

  • @@||example.com^generichide — disables generic cosmetic rules on any pages at example.com and all subdomains.

genericblock

Disables generic basic rules on pages that correspond to exception rule.

  • @@||example.com^$genericblock — disables generic basic rules on any pages at example.com and all subdomains.

Advanced modifiers

These modifiers are able to completely change the behaviour of basic rules.

important

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

Example 1:
||example.org^$important
@@||example.org^

||example.org^$important will block all requests despite of the exception rule.

Example 2:
||example.org^$important
@@||example.org^$important

Now the exception rule also has $important modifier so it will prevail.

Example 3:

The $important modifier will be ignored if a document-level exception rule is applied to the document.

||example.org^$important
@@||test.org^$document

If a request to example.org is sent from the test.org domain, the rule won't be applied despite it has the $important modifier.

badfilter

Compatibility with different versions of AdGuard

badfilter modifier is currently only available in AdGuard browser extensions. It will be added to other AdGuard products later.

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 examples
  • ||example.com$badfilter disables ||example.com
  • ||example.com$image,badfilter disables ||example.com,image
  • @@||example.com$badfilter disables @@||example.com
  • ||example.com$domain=domain.com,badfilter disables ||example.com$domain=domain.com

Compatibility with different versions of AdGuard

Below modifiers from this section are only available in AdGuard for Windows, macOS and Android. Browser extension capabilities are limited by browser itself and some methods are just not available to them.

empty

Usually, blocked requests look like a server error to browser. If you use empty modifier, AdGuard will emulate a blank response from the server with200 OK status.

empty example
  • ||example.org^$empty — returns an empty response to all requests to example.org and all subdomains.

mp4

As a response to blocked request AdGuard returns a short video placeholder.

mp4 example
  • ||example.com/videos/$mp4 — block a video downloads from ||example.com/videos/* and changes the response to a video placeholder.

replace

This modifier completely changes the rule behavior. If it is applied, the rule will not block the request. The response is going to be modified instead.

Please note

You will need some knowledge of regular expressions to use this modifier.

Compatibility with different versions of AdGuard

Rules are supported by AdGuard for Windows, Mac, Android and by the AdGuard's Firefox add-on.
This type of rules don't work in extensions for other browsers because they are unable to modify content on network level.

replace rules features
  • replace rules apply to any text response, but will not apply to binary (media, image, object, etc).
  • replace rules do not apply if the size of the original response is more than 3MB.
  • If a replace rule was applied to the page, other rules (e.g. cosmetic) are not going to be applied to the code.
  • replace rules have a higher priority than other basic rules (except for exception rules). So if the request corresponds to two different rules one of which has a replace modifier, this rule will be applied.
replace syntax

In general, replace syntax is similar to replacement with regular expressions in Perl.

replace = "/" regex "/" replacement "/" modifiers
  • regex — regular expression.
  • replacement — a string, that will be used to replace the string corresponding toregex.
  • modifiers — regular expression flags. For example, i - insensitive search, ors - single-line mode.

In replace value, two characters must be escaped: comma (,) and ($). Use (\) for it. For example, escaped comma looks like this: \,.

replace examples
||damoh.golem.de^$replace=/(<VAST[\s\S]*?>)[\s\S]*<\/VAST>/\$1<\/VAST>/

There are three parts in this rule:

  • Regular expression: (<VAST(.|\s)*?>)(.|\s)*<\/VAST>
  • Replacement \$1<\/VAST> (please note, that $ is escaped)
  • regular expression flags: i (insensitive search)

You can see how this rule works here:
http://regexr.com/3cesk

csp

This modifier completely changes the rule behavior. If it is applied to a rule, it will not block the matching request. The response headers are going to be modified instead.

In order to use this type of rules, it is required to have the basic understanding of the Content Security Policy security layer.

For the requests matching a $csp rule, we will strengthen response's security policy by adding additional content security policy equal to the $csp modifier contents. $csp rules are applied independently from any other rule type. Other basic rules have no influence on it.

Multiple rules matching a single request.
In case if multiple $csp rules match a single request, we will apply each of them.

csp Syntax

$csp value syntax is similar to the Content Security Policy header syntax.

$csp value can be empty in the case of exception rules. See examples section for further information.

Limitations

  1. Please note, that there're a few characters forbidden in the $csp value: (,), ($)
  2. csp rules support limited list of modifiers: domain, important, subdocument
  3. Rules with report-* directives are considered invalid.
csp examples
  • ||example.org^$csp=frame-src 'none' — prohibits all frames on example.org and it's subdomains.
  • @@||example.org/page/*$csp=frame-src 'none' — disables all rules with the $csp modifier exactly matching frame-src 'none' on all the pages matching the rule pattern. For instance, the rule above.
  • @@||example.org/page/*$csp — disables all the $csp rules on all the pages matching the rule pattern.
  • ||example.org^$csp=script-src 'self' 'unsafe-eval' http: https: — disables inline scripts on all the pages matching the rule pattern.

network

This is basically a Firewall-kind of rules allowing to fully block or unblock access to a specified remote address.

Compatibility with different versions of AdGuard

Only AdGuard for Windows, Mac, Android are technically capable of using this type of rules.

  1. $network rules match IP addresses only! You cannot use it to block or unblock access to a domain.
  2. To match an IPv6 address, you have to use the collapsed syntax, e.g. use [2001:4860:4860::8888]$network instead of [2001:4860:4860:0:0:0:0:8888]$network.
  3. A whitelist $network rule makes AdGuard bypass data to the matching endpoint, e.g. there will be no further filtering at all.
network examples
  • 174.129.166.49:3478^$network - blocks access to 174.129.166.49:3478 (but not to 174.129.166.49:34788).
  • [2001:4860:4860::8888]:443^$network - blocks access to [2001:4860:4860::8888]:443.
  • 174.129.166.49$network - blocks access to 174.129.166.49:*.
  • @@174.129.166.49$network - makes AdGuard bypass data to the endpoint. No other rules will be applied.

app

This modifier lets you narrow the rule coverage down to a specific application (or a list of applications). This might be not too important on Windows and Mac, but this is very important on Mobile where some of the filtering rules must be application-specific.

  • Android - use the apps' package names (i.e. org.example.app).
  • Windows - use the process name (i.e. chrome.exe).
  • Mac - use the process name (i.e. firefox-bin).

In the case of Android, use the apps' package names (i.e. org.example.app). In the case of Windows

app examples
  • ||baddomain.com^$app=org.example.app — a rule to block requests that match the specified mask, and are sent from the com.adguard.android Android app.
  • ||baddomain.com^$app=org.example.app1|org.example.app2 — the same rule, but it works for both org.example.app1 and org.example.app2 apps.

If you want the rule not to be applied to certain apps, start the app name with ~ sign.

app and ~ examples
  • ||baddomain.com^$app=~org.example.app — a rule to block requests that match the specified mask, and are sent from any app save for the org.example.app.
  • ||baddomain.com^$domain=~org.example.app1|~org.example.app2 — same as above, but now two apps are excluded: org.example.app1 and org.example.app2.

Cosmetic rules

As the name suggests, cosmetic rules are used not for blocking ad requests, but for changing the page appearance. They can hide the elements or even convert the overall style of pages.

Work with cosmetic rules requires the basic knowledge of HTML and CSS. So, if you want to learn how to make such rules, we recommend to get acquainted with this documentation.

Element hiding rules

Element hiding rules are used to hide the elements of web pages. It is similar to applying { display: none; } style to selected element.

Element hiding rules syntax

   rule = [domains] "##" selector
domains = [domain0, domain1[, ...[, domainN]]]
  • selectorCSS selector, defines the elements to be hidden.
  • domains — domain restriction for the rule.

If you want to limit the rule application area to certain domains, just enter them separated with commas. For example: example.org,example.com##selector.

Please note that this rule will be also applied to all subdomains of example.org and example.com.

If you want the rule not to be applied to certain domains, start a domain name with ~ sign. For example:
~example.org##selector.

You can use both approaches in a single rule. For example, example.org,~subdomain.example.org##domain will work for example.org and all subdomains, except subdomain.example.org.

Please note

Element hiding rules are not dependent on each other. If there is a rule example.org##selector in the filter and you add ~example.org##selector both rules will be applied independently.

Element hiding rules examples

  • example.com##.textad — hides a div with a class textad at example.com and all subdomains.
  • example.com,example.org###adblock - hides an element with attribute id equals adblock at example.com, example.org and all subdomains.
  • ~example.com##.textad - hides a div with a class textad at all domains, except example.com and it's subdomains.

Element hiding rules exceptions

Exceptions can disable some rules on particular domains. They are very similar to usual exception rules, but instead of ## you have to use #@#.

For example, there is a rule in filter:

##.textad

If you want to disable it for example.com, you can create an exception rule:

example.com#@#.textad

We recommend to use this kind of exceptions only if it is not possible to change the hiding rule itself. In other case it is better to change the original rule, using domain restrictions.

Please note

Exception rule without any particular domains in it does not make sense and will be ignored.

Cosmetic css rules

Sometimes, simple hiding of an element is not enough to deal with advertising. For example, blocking an advertising element can just break the page layout. In this case AdGuard can use rules that are much more flexible than hiding rules. With this rules you can basically add any CSS styles to the page.

Cosmetic css rules syntax

   rule = [domains] "#$#" selector "{" style "}"
domains = [domain0, domain1[, ...[, domainN]]]
  • selectorCSS selector, defines the elements we want to apply the style to.
  • domains — domain restriction for the rule. Same principles as in element hiding rules.
  • style — CSS style, that we want to apply to selected elements.

Cosmetic css rules examples

example.com#$#body { background-color: #333!important; }

This rule will apply a style background-color: #333!important; to the body element at example.com and all subdomains.

Cosmetic css rules exceptions

Just like with element hiding, there is a type of rules that disable the selected CSS style rule for particular domains.
Exception rules syntax is almost the same, you just have to change #$# to #@$#.

For example, there is a rule in filter:

#$#.textad { visibility: hidden; }

If you want to disable it for example.com, you can create an exception rule:

example.com#@$#.textad { visibility: hidden; }

We recommend to use this kind of exceptions only if it is not possible to change the CSS rule itself. In other case it is better to change the original rule, using domain restrictions.

Extended CSS selectors

CSS 3.0 is not always enough to block ads. To solve this problem AdGuard extends CSS capabilities by adding support for the new pseudo-elements. To use extended CSS selectors we have developed a separate open source module.

Backward compatibility

In common filters we use so-called backward compatible syntax. The thing is, extended pseudo-classes can break cosmetic rules in previous versions of AdGuard or in other ad blockers that do not support extended CSS. For example, instead of pseudo-class :has(selector) it is possible to use [-ext-has="selector"] attribute.

Application area

Extended selectors can be used in any cosmetic rule, whether they are element hiding rules or CSS rules.

Pseudo-class :has()

Draft CSS 4.0 specification describes pseudo-class :has. Unfortunately, it is not yet supported by browsers.

:has() syntax
:has(selector)

Backward compatible syntax:

[-ext-has="selector"]

Supported synonyms for better compatibility: :-abp-has, :if.

Pseudo-class :has() selects the elements that includes the elements that fit to selector.

:has() examples

Selecting all div elements, which contain an element with the banner class.

HTML code

<div>Do not select this div</div>
<div>Select this div<span class="banner"></span></div>

Selector

div:has(.banner)

Backward compatible syntax:

div[-ext-has=".banner"]

Pseudo-class :if-not()

This pseudo-class is basically a shortcut for :not(:has()). It is supported by ExtendedCss for better compatibility with some filters subscriptions, but it is not recommended to use it in AdGuard filters. The rationale is that one day browsers will add :has native support, but it will never happen to this pseudo-class.

Pseudo-class :contains()

This pseudo-class principle is very simple: it allows to select the elements that contain specified text or which content matches a specified regular expression. Please note, that this pseudo-class uses innerText element property for matching (and not the innerHTML).

:contains() syntax
// matching by plain text
:contains(text)

// matching by a regular expression
:contains(/regex/)

Backward compatible syntax:

// matching by plain text
[-ext-contains="text"]

// matching by a regular expression
[-ext-contains="/regex/"]

Supported synonyms for better compatibility: :-abp-contains, :has-text.

:contains() examples

Selecting all div elements, which contain text banner.

HTML code

<div>Do not select this div</div>
<div id="selected">Select this div (banner)</div>
<div>Do not select this div <div class="banner"></div></div>

Selector

// matching by plain text
div:contains(banner)

// matching by a regular expression
div:contains(/this .* banner/)

Backward compatible syntax:

// matching by plain text
div[-ext-contains="banner"]

// matching by a regular expression
div[-ext-contains="/this .* banner/"]

Please note that in this example only a div with id=selected will be selected, because the next element does not contain any text (banner is a part of code, not text).

Pseudo-class :matches-css()

These pseudo-classes allow to select an element by its current style property. The work of this pseudo-class is based on using the window.getComputedStyle function.

:matches-css() syntax
/* element style matching */
selector:matches-css(property-name ":" pattern)

/* ::before pseudo-element style matching */
selector:matches-css-before(property-name ":" pattern)

/* ::after pseudo-element style matching */
selector:matches-css-after(property-name ":" pattern)

Backward compatible syntax:

selector[-ext-matches-css="property-name ":" pattern"]
selector[-ext-matches-css-after="property-name ":" pattern"]
selector[-ext-matches-css-before="property-name ":" pattern"]
property-name

A name of CSS property to check the element for.

pattern

This can be either a value pattern that is using the same simple wildcard matching as in the basic url filtering rules or it can be a regular expression. For this type of matching, AdGuard always does matching in a case insensitive manner.

In the case of a regular expression, the pattern looks like /regex/.

  • For non-regex patterns, (,),[,] must be unescaped, because we require escaping them in the filtering rules.
  • For regex patterns, ["],[,],[\] should be escaped, because we manually escape those in extended-css-selector.js.
:matches-css() examples

Selecting all div elements which contain pseudo-class ::before with specified content.

HTML code

<style type="text/css">
    #to-be-blocked::before {
        content: "Block me"
    }
</style>
<div id="to-be-blocked" class="banner"></div>
<div id="not-to-be-blocked" class="banner"></div>

Selector

// Simple matching
div.banner:matches-css-before(content: block me)

// Regular expressions
div.banner:matches-css-before(content: /block me/)

Backward compatible syntax:

// Simple matching
div.banner[-ext-matches-css-before="content: block me"]

// Regular expressions
div.banner[-ext-matches-css-before="content: /block me/"]

Pseudo-class :properties()

Originally, this pseudo-class was introduced by ABP.

On the surface this pseudo class is somewhat similar to :matches-css. However, it is very different under the hood. :matches-css is based on using window.getComputedStyle while :properties is based on scanning page stylesheets and using them to lookup elements.

In short, :matches-css is about "Computed" tab of the dev tools while :properties is about "Styles" tab:

Another notable difference is that there is no special "-before"/"-after" pseudo-classes. :properties matching strips both ::before and ::after pseudo-elements from the selectors found in the stylesheets.

Limitations

  • Cross-origin stylesheets are ignored
  • At-rules are also ignored. This means that imported (@import) stylesheets and @media groups are ignored.
:properties() syntax
/* element style matching */
selector:properties(property-name ":" pattern)

Backward compatible syntax:

selector[-ext-properties="property-name ":" pattern"]

Supported synonyms for better compatibility: :-abp-properties.

property-name

A name of CSS property to check the element for.

pattern

This can be either a value pattern that is using the same simple wildcard matching as in the basic url filtering rules or it can be a regular expression. For this type of matching, AdGuard always does matching in a case insensitive manner.

In the case of a regular expression, the pattern looks like /regex/.

  • For non-regex patterns, (,),[,] must be unescaped, because we require escaping them in the filtering rules.
  • For regex patterns, ",\ should be escaped, because we manually escape those in extended-css-selector.js.
:properties() examples

Selecting all div elements which contain any pseudo-class (::before or ::after) with the specified content.

HTML code

<style type="text/css">
    #to-be-blocked::before {
        content: "Block me"
    }
</style>
<div id="to-be-blocked" class="banner"></div>
<div id="not-to-be-blocked" class="banner"></div>

Selector

// Simple matching
div.banner:properties(content: block me)

// Regular expressions
div.banner:properties(content: /block me/)

Backward compatible syntax:

// Simple matching
div.banner[-ext-properties="content: block me"]

// Regular expressions
div.banner:properties(content: /block me/)

Selectors debugging mode

Sometimes, you might need to check the performance of a given selector or a stylesheet. In order to do it without interacting with javascript directly, you can use a special debug style property. When ExtendedCss meets this property, it enables the "debug"-mode either for a single selector or for all selectors depending on the debug value.

Debugging a single selector

#$#.banner { display: none; debug: true; }

Enabling global debug

#$#.banner { display: none; debug: global; }

Testing extended selectors

To load ExtendedCss to a current page, copy and execute the following code in a browser console:

!function(E,x,t,C,s,s_){C=E.createElement(x),s=E.getElementsByTagName(x)[0],C.src=t,
C.onload=function(){alert('ExtCss loaded successfully')},s.parentNode.insertBefore(C,s)}
(document,'script','https://AdguardTeam.github.io/ExtendedCss/extended-css.min.js')

Alternatively, install an "ExtendedCssDebugger" userscript: https://github.com/AdguardTeam/Userscripts/blob/master/extendedCssDebugger/extended-css.debugger.user.js

You can now use the ExtendedCss constructor in the global scope, and its method ExtendedCss.query as document.querySelectorAll.

var selectorText = "div.block[-ext-has='.header:matches-css-after(content: Anzeige)']";

ExtendedCss.query(selectorText) // returns an array of Elements matching selectorText

HTML filtering rules

In most cases, the basis and cosmetic rules are enough to filter ads. But sometimes it is necessary to change the HTML-code of the page itself before it is loaded. This is when you need filtering rules for HTML content. They allow to indicate the HTML elements to be cut out before the browser loads the page.

Compatibility with different versions of AdGuard

Rules are supported by AdGuard for Windows, Mac, Android and by the AdGuard's Firefox add-on.
This type of rules don't work in extensions for other browsers because they are unable to modify content on network level.

HTML filtering rules syntax

      rule = [domains] "$$" tagName [attributes]
   domains = [domain0, domain1[, ...[, domainN]]]      
attributes = "[" name0 = value0 "]" "[" name1 = value2 "]" ... "[" nameN = valueN "]"
  • tagName — name of the element in lower case, for example div or script.
  • domains — domain restriction for the rule. Same principles as in element hiding rules syntax.
  • attributes — a list of attributes, that limit the elements selection. name - attribute name, value - substring, that is contained in attribute value.

HTML filtering rules example

HTML code

<script data-src="/banner.js"></script>

Rule

example.org$$script[data-src="banner"]

This rule will delete all script elements with data-src attribute that contain banner substring. The rule will only work for example.org and all it's subdomains.

Special attributes

In addition to usual attribures, which value is every element checked for, there is a set of special attributes that change the way a rule works. Below there is a list of these attributes:

tag-content

This is the most frequently used special attribute. It limits selection with those elements whose innerHTML code contains the specified substring.

For example, let's take a look at this HTML code:

<script type="text/javascript">
    document.write('<div>banner text</div>" />');
</script>

Following rule will delete all script elements with a banner substring in their code:

$$script[tag-content="banner"]

Nested elements

If we are dealing with multiple nested elements and they all fall within the same HTML filtering rule, they all are going to be deleted.

wildcard

This special attribute works almost like tag-content and allows you to check the innerHTML code of the document. Rule will check if HTML code of the element fits to the search pattern.

For example:
$$script[wildcard="*banner*text*"]

It will check, if the element's code contains two consecutive substrings banner and text.

max-length

Specifies the maximum length for content of HTML element. If this parameter is set and the content length exceeds the value - a rule does not apply to the element.

Default setting

If this parameter is not specified, the max-length is considered to be 8192.

For example:

$$div[tag-content="banner"][max-length="400"]

This rule will remove all the div elements, whose code contains the substringbanner and the length of which does not exceed 400 characters.

min-length

Specifies the minimum length for content of HTML element. If this parameter is set and the content length is less than preset value - a rule does not apply to the element.

For example:

$$div[tag-content="banner"][min-length="400"]

This rule will remove all the div elements, whose code contains the substringbanner and the length of which exceeds 400 characters.

parent-elements

This attribute seriously modifies the rule behaviour. A common HTML filtering rule uses attributes to find and delete elements on the page. If parent-elements is set, then the element's parent element (with a name specified by parent-elements attribute) will be deleted instead.

Here is an example:

HTML code

<table style="background: url('http://domain.com/banner.gif')">
    <tr>
        <td>
            <a href="http://example.org/ads">TEXT ADS</a>
        </td>
    </tr>
</table>

The problem with this code is that cutting out ads is not enough here. The banner is displayed using the parent table (as a background). This is where we can use the parent-elements.

Let's use the following rule to block the entire table:

$$a[href="example.org/ads"][parent-elements="table"]

When AdGuard finds an element a with a href attribute that contain example.org/ads, rather then cut it out, it will keep looking for the closest parent element table and will cut it out instead.

You can specify few parent elements separated by commas. The closest one will be blocked.

parent-search-level

Specifies the maximum parent element search depth. The defaul maximum search depth is 3.
That was set in order not to cut too much, if HTML page changes. Do not use too large values for this attribute.

HTML filtering rules exceptions

Similar to hiding rules, there is a special type of rules that disable the selected HTML filtering rule for particular domains.
The syntax is the same, you just have to change $$ to $@$.

For example, there is a rule in filter:

$$script[tag-content="banner"]

If you want to disable it for example.com, you can create an exception rule:

example.com$@$script[tag-content="banner"]

Javascript rules

AdGuard supports a special type of rules that allows you to inject any javascript code to websites pages.

Restrictions

Please note that this type of rules can be used only in trusted filters. This category includes your own User filter and all the filters created by AdGuard Team.

Javascript rules syntax

rule = [domains]  "#%#" script
  • domains — domain restriction for the rule. Same principles as in element hiding rules.
  • script — arbitrary javascript code in one string.

Javascript rules examples

  • example.org#%#window.__gaq = undefined; — executes the code window.__gaq = undefined; on all pages at example.org and all subdomains.

Javascript rules exceptions

Similar to hiding rules, there is a special type of rules that disable the selected javascript rule for particular domains.
The syntax is the same, you just have to change #%# to #@%#.

For example, there is a rule in filter:

#%#window.__gaq = undefined;

If you want to disable it for example.com, you can create an exception rule:

example.com#@%#window.__gaq = undefined;

Information for filters maintainers

If you maintain a third-party filter that is known to AdGuard, you might be interested in the information presented in this section. Please note, that hints will be applied to registered filters only. The filter is considered to be registered and known by AdGuard, if it is present in the known filters index. If you want your filter to be registered, please file an issue to AdguardFilters repo.

Pre-processor directives

We provide multiple pre-processor directives that can be used by filters maintainers to improve compatibility with different ad blockers.

Syntax

!#if condition
Anything goes here
!#include URL_or_a_relative_path
!#endif
  • !#if, !#endif -- filters maintainers can use these conditions to supply different rules depending on the ad blocker type.
  • condition -- just like in some popular programming languages, pre-processor conditions are based on constants declared by ad blockers. Ad blocker authors define on their own what exact constants do they declare.
  • !#include -- this directive allows to include contents of a specified file into the filter.

Conditions

When an adblocker encounters an !#if directive, followed eventually by an !#endif directive, it will compile the code between the directives only if the specified condition is true. Condition supports all the basic logical operators.

Example:

!#if (adguard && !adguard_ext_safari)
||example.org^$third-party
!#endif

Including a file

The !#include directive supports only files from the same origin to make sure that the filter maintainer is in control of the specified file. The included file can also contain pre-processor directives (even other !#include directives).

Ad blockers should consider the case of recursive !#include and implement a protection mechanism.

Examples

Filter URL: https://example.org/path/filter.txt

!
! Valid (same origin):
!#include https://example.org/path/includedfile.txt
!
! Valid (relative path):
!#include /includedfile.txt
!#include ../path2/includedfile.txt
!
! Invalid (another origin):
!#include https://example.com/path/includedfile.txt

Remarks

  • If included file is not found or unavailable, the whole filter update should fail.
  • A conditional directive beginning with an #if directive must explicitly be terminated with an #endif directive.
  • Whitespaces matter. !#if is a valid directive, while !# if is not.

AdGuard-specific

  • Any mistake in a pre-processor directive will lead to AdGuard failing the filter update in the same way as if the filter URL was unavailable.
  • Pre-processor directives can be used in the user filter (or in the custom local filters). Same-origin limitation should be disabled for local filters.

What constants do we declare

  • adguard -- Declared always. Lets maintainers know that this is one of AdGuard products. Should be enough in 95% of cases.

Product-specific constants for some rare cases when you need a rule to work (or not work) in a specific product only:

  • adguard_app_windows -- AG for Windows
  • adguard_app_mac -- AG for Mac
  • adguard_app_android -- AG for Android
  • adguard_app_ios -- AG for iOS
  • adguard_ext_chromium -- AG browser extension for Chrome
  • adguard_ext_firefox -- AG browser extension for Firefox
  • adguard_ext_edge -- AG browser extension for Edge
  • adguard_ext_safari -- AG browser extension for Safari
  • adguard_ext_opera -- AG browser extension for Opera
  • adguard_ext_android_cb -- AG content blocker for Samsung/Yandex

Special case: ext_ublock. This constant is declared when a ublock version of a filter is compiled by the FiltersRegistry.

Hints

"Hint" is a special comment, instruction to the filters compiler used on the server side (see FiltersRegistry).

Hints syntax

!+ HINT_NAME1(PARAMS) HINT_NAME2(PARAMS)

Note, that you can apply multiple hints.

NOT_OPTIMIZED hint

For large filters, AdGuard compiles two versions: full and optimized. Optimized version is much smaller and does not contain rules which are not used at all or used rarely. More information about rules optimization you may find in this article.

Example of optimized version of the English filter: https://filters.adtidy.org/extension/edge/filters/2_optimized.txt.

Examples:

This rule won't be optimized:

!+ NOT_OPTIMIZED
||example.org^

This rule won't be optimized and will be available for Android only:

!+ NOT_OPTIMIZED PLATFORM(android)
||example.org^

PLATFORM and NOT_PLATFORM hints

Specify which platforms can apply this rule. List of existing platforms:

Examples:

This rule will be available for Windows, Mac, and Android only:

!+ PLATFORM(windows,mac,android)
||example.org^

This rule will be available for every platform except Safari extension, iOS, and Android content blocker:

!+ NOT_PLATFORM(ext_safari, ext_android_cb, ios)
||example.org^

Good luck with creating filters!

We wish you luck with creating you own ad filters.

If you need an advice on how to create your own filters properly, our forum has a special section dedicated to writing your own filtering rules.