Writing Adblock Plus filters
Current Adblock Plus versions allow you to "tweak" your filters in many different ways. This document explains the choices that you have and how they can be used.
Disclaimer: All filter examples given here are really only examples and are not meant to be used.
Introduction to Adblock Plus filters
The options described in this section should be enough for users who have to create a filter occasionally.
Basic filter rules
The most trivial filter you can define is of course the address of banner you want to block. However, often this address changes every time you open a page. For example it could be http://example.com/ads/banner123.gif
where 123 is a random number. Here blocking the complete address won't help you, you need a more general filter — like http://example.com/ads/banner*.gif
. Or maybe even http://example.com/ads/*
.
Note: Make sure that you are not replacing too much by wildcards. The filter http://example.com/*
will definitely block all banners but it will also block everything else from example.com that you still might want to see.
Defining exception rules
Once in a while you may notice that one of your filters, that normally works well, is blocking something that it shouldn't block. You don't want to remove this filter but you still don't want it to match in this one case.
That's what exception rules are good for — they allow you to define cases where filters shouldn't be applied. For example if you are unhappy with your filter adv
blocking http://example.com/advice.html
, you can define an exception rule @@advice
. Exception rules are no different from filter rules, you can use wildcards or regular expressions. You only have to precede them by @@
to indicate an exception rule.
Exception rules can do more. If you specify $document
option you will get an exception for the entire page. For example, if your exception rule is @@||example.com^$document
and you open some page from example.com — Adblock Plus will be entirely disabled on this page and nothing will be blocked.
Matching at beginning/end of an address
Usually Adblock Plus treats every filter as if it had a wildcard at its beginning and end, e.g. there is not difference between the filters ad
and *ad*
. While this is usually unproblematic, sometimes you wish that the filter you defined only matches at the beginning or end of an address. For example you might want to block all Flash, but if you add the filter swf
the address http://example.com/swf/index.html
will also be blocked.
Solution to this problem: add a pipe symbol to the filter to show that there should be definitely the end of the address at this point. For example the filter swf|
will block http://example.com/annoyingflash.swf
but not http://example.com/swf/index.html
. And the filter |http://baddomain.example/
will block http://baddomain.example/banner.gif
but not http://gooddomain.example/analyze?http://baddomain.example
.
Sometimes one wants to block http://example.com/banner.gif
as well as https://example.com/banner.gif
and http://www.example.com/banner.gif
. This can be achieved by putting two pipe symbols in front of the filter which makes sure the filter matches at the beginning of the domain name: ||example.com/banner.gif
will block all these addresses while not blocking http://badexample.com/banner.gif
or http://gooddomain.example/analyze?http://example.com/banner.gif
(requires Adblock Plus 1.1 or higher).
Marking separator characters
Often you need to accept any separator character in a filter. For example, you might write a filter that blocks http://example.com/
and http://example.com:8000/
but not http://example.com.ar/
. Here the symbol ^ can be used as a placeholder for a single separator character: http://example.com^
(requires Adblock Plus 1.1 or higher).
Separator character is anything but a letter, a digit, or one of the following: _ - . %. The end of the address is also accepted as separator. In the following example all separator characters are shown in red: http://example.com:8000/foo.bar?a=12&b=%D1%82%D0%B5%D1%81%D1%82. So this address can be blocked with the filter ^example.com^
or ^%D1%82%D0%B5%D1%81%D1%82^
or ^foo.bar^
.
Comments
Any rule that starts with an exclamation mark is considered a comment. It will still show up in the filter list but in grey instead of black. Adblock Plus will ignore this rule for actual blocking so it is safe to write there whatever you want. You can place a comment rule above a real filter to describe what it is doing. Or you can put a comment on top of your filter list stating your authorship (most filter list authors do that).
Special comments
Special comments will only have an effect in downloaded filter lists, not in custom filters. Special comments must be given at the top of the filter list right below the header. They can set a number of parameters for the filter list:
-
! Homepage: http://example.com/
This comment determines which webpage should be linked as filter list homepage.
-
! Title: FooList
This comment sets a fixed title for the filter list. If this comment is present the user will no longer be able to change the title.
-
! Expires: 5 days
This comment sets the update interval for the filter list, the value can be given in days (e.g.
5 days
) or hours (e.g.8 hours
). Any value between 1 hour and 14 days is possible. Note that the update will not necessarily happen after this time interval. The actual update time is slightly randomized and depends on some additional factors to reduce server load. -
! Redirect: http://example.com/list.txt
This comment indicates that the filter list has moved to a new download address. Adblock Plus will ignore any file contents beyond that comment and immediately try downloading from the new address. In case of success the address of the filter list will be updated in the settings. This comment is ignored if the new address is the same as the current address, meaning that it can be used to enforce the "canonical" address of the filter list.
-
! Version: 1234
This comment defines a numerical version of the filter list. This version number will be displayed in issue reports and can be used to verify that the report refers to the current version of the filter list.
Advanced features
The features described in this section are usually used only by power users and filterlist creators. Feel free to skip it.
Specifying filter options
Adblock Plus allows you to specify a number of options to modify the behavior of a filter. You list these options separated with commas after a dollar sign ($) at the end of the filter, for example:
*/ads/*$script,match-case
Here */ads/*
is the actual filter and script
and match-case
are its options. Currently the following options are supported:
- Type options: determine which types of elements a filter can block (or whitelist in case of an exception rule). Multiple type options can be specified to indicate that the filter should be applied to several types of elements. Possible types are:
script
— external scripts loaded via HTML script tagimage
— regular images, typically loaded via HTML img tagstylesheet
— external CSS stylesheet filesobject
— content handled by browser plugins, e.g. Flash or Javaxmlhttprequest
— requests started using theXMLHttpRequest
object orfetch()
APIsubdocument
— embedded pages, usually included via HTML framesping
— requests started by<a ping>
ornavigator.sendBeacon()
(Adblock Plus 2.7.1 or higher required)websocket
— requests initiated viaWebSocket
object (Adblock Plus 2.8 or higher required)webrtc
— connections opened viaRTCPeerConnection
instances to ICE servers (Adblock Plus 1.13.3 for Chrome and Opera, 3.0 for Firefox, or higher required)document
— the page itself (only exception rules can be applied to the page)elemhide
— for exception rules only, similar todocument
but only disables element hiding rules on the page rather than all filter rules (Adblock Plus 1.2 or higher required)generichide
— for exception rules only, similar toelemhide
but only disables generic element hiding rules on the page (Adblock Plus 2.6.12 or higher required)genericblock
— for exception rules only, just likegenerichide
but disables generic blocking rules (Adblock Plus 2.6.12 or higher required)popup
— pages opened in a new tab or windowother
— types of requests not covered in the list above
background
,xbl
anddtd
are outdated and should no longer be used. - Inverse type options: specify the element types the filter should not be applied to. Possible inverse type options:
~script
,~image
,~stylesheet
,~object
,~xmlhttprequest
,~subdocument
,~document
,~elemhide
,~other
- Restriction to third-party/first-party requests: If the
third-party
option is specified, the filter is only applied to requests from a different origin than the currently viewed page. Similarly,~third-party
restricts the filter to requests from the same origin as the currently viewed page. - Domain restrictions: The option
domain=example.com
means that the filter should only be applied on pages from "example.com" domain. Multiple domains can be specified using "|" as separator: with the optiondomain=example.com|example.net
the filter will only be applied on pages from "example.com" or "example.net" domains. If a domain name is preceded with "~", the filter should not be applied on pages from this domain. For example,domain=~example.com
means that the filter should be applied on pages from any domain but "example.com" anddomain=example.com|~foo.example.com
restricts the filter to the "example.com" domain with the exception of "foo.example.com" subdomain. -
Sitekey restrictions: The option
sitekey=abcdsitekeydcba
means that the filter should only be applied on pages that provide a public key and a signature which can be verified by that very same public key that is also contained in the filter (but without the trailing =). Multiple sitekeys can be specified using "|" as separator: with the optionsitekey=abcdsitekeydcba|bcdesitekeyedcb
the filter will only be applied on pages providing either sitekey "abcdsitekeydcba" or "bcdesitekeyedcb". This is similar to domain restrictions but allows covering scenarios where a single filter should apply to a very large number of domains. Note that sitekey restrictions require modifications on the server-side. -
Content Security Policies: The option
csp=script-src: 'none'
causes a Content Security Policy header ofscript-src: 'none'
to be injected into HTTP responses for requested documents matching the filter — assuming that exception rules with the same option don't also match and that the document isn’t whitelisted. The Content Security Policyscript-src: 'none'
would in turn block all scripts — including inline — for the document. This filter option should generally be avoided, except as a last resort to counter advanced circumvention. (Adblock Plus 3.1 or higher required.) match-case
— makes the filter only apply to addresses with matching letter case, e.g. the filter*/BannerAd.gif$match-case
will blockhttp://example.com/BannerAd.gif
but nothttp://example.com/bannerad.gif
.
Using regular expressions
If you want even more control about what your filters match and what they don't match, you can use regular expressions. For example the filter /banner\d+/
will match banner123
and banner321
but not banners
. You can check out documentation on regular expressions to learn how to write them.
Note: For performance reasons it is recommended not to use regular expressions if they can be avoided.
Element hiding
Basic rules
Sometimes you will find advertisements that can't be blocked because they are embedded as text in the web page itself. If you look at the source code of the web page you might find something like this:
<div class="textad"> Cheapest tofu, only here and now! </div> <div id="sponsorad"> Really cheap tofu, click here! </div> <textad> Only here you get the best tofu! </textad>
You need to download the web page so you will necessarily download the advertisements. All you can do here is to hide the advertisement so you don't need to see it. That's what element hiding is meant for.
The first advertisement above is contained inside an element with class attribute "textad". The following rule will hide exactly any such element: ##.textad
. Here ## marks an element hiding rule while the rest is a selector identifying the elements that need to be hidden. You can hide elements by their id attribute similarly, ###sponsorad
will hide the second advertisement. And you can hide elements by element name, e.g. ##textad
for the third advertisement.
The Element Hiding Helper extension helps selecting the correct element and writing the corresponding rule without having to view the source code of the page. Basic HTML knowledge is useful nevertheless.
Note: Element hiding works very differently from normal filters. This has the implication that no wildcards are supported in element hiding rules.
Limiting rules to certain domains
Usually you want to hide a specific ad on one specific site, you don't want your rule to be applied on other sites. For example the rule ##.sponsor
might hide valid code on some sites. But if you write it as example.com##.sponsor
it will be applied on http://example.com/
and http://something.example.com/
but not on http://example.org/
. You can also specify multiple domains — simply separate them with commas: domain1.example,domain2.example,domain3.example##.sponsor
.
If a domain name is preceded with "~", the rule will not be applied on pages from this domain (requires Adblock Plus 1.1 or higher). For example, ~example.com##.sponsor
will be be applied on pages from any domain but "example.com" and example.com,~foo.example.com##.sponsor
makes the rule apply on "example.com" domain with the exception of "foo.example.com" subdomain.
Note: Due to the way how element hiding is implemented, you really can only limit it to full domain names. You cannot use any other part of the address and you cannot use domain
as a replacement for domain.example,domain.test
.
Note: Element hiding rules with domain limitation can be used to hide browser's user interface elements as well. For example the filter rule browser##menuitem#javascriptConsole
will hide the JavaScript Console entry in Firefox's Tools menu.
Attribute selectors
Some advertisers don't make it easy for you — their text advertisements have neither an id nor a class attribute. You can use other attributes to hide those, for example ##table[width="80%"]
will hide tables with width attribute set to 80%. If you don't want to specify the full value of the attribute, ##div[title*="adv"]
will hide all div elements with title attribute containing the string "adv". You can also check the beginning and the end of an attribute, for example ##div[title^="adv"][title$="ert"]
will hide div elements with title starting with "adv" and ending with "ert". As you see, you can also use multiple conditions — table[width="80%"][bgcolor="white"]
will match tables with width attribute set to 80% and bgcolor attribute set to white.
Advanced selectors
In general, any CSS selector supported by Firefox can be used for element hiding. For example the following rule will hide anything following a div element with class "adheader": ##.adheader + *
. For a full list of CSS list see W3C CSS specification (note that not all selectors are supported by Firefox yet). Please keep in mind that browsers are slower to process these selectors than selectors based on class
or id
attribute only.
Note: This functionality is for advanced users only, you should be comfortable with CSS selectors to use it. Adblock Plus won't be able to check the syntax of the selector you are adding, if you use invalid CSS syntax you might break other (valid) rules you have. Check JavaScript Console for CSS errors.
Extended CSS selectors (Adblock Plus specific)
Sometimes the standard CSS selectors aren't powerful enough to hide an advertisement. For those cases we have added some new selectors, namely :-abp-has()
, :-abp-contains()
and :-abp-properties()
(requires Adblock Plus 1.13.3 or higher for Chrome and Opera).
When writing an element hiding filter that makes use of these extended selectors you must use the #?#
syntax, e.g. example.com#?#selector
. But it's important to note that doing so carries a performance impact, so do so sparingly and make sure those filters are specific to as few domains and elements as possible.
:-abp-properties()
:-abp-properties(properties)
will select elements based upon stylesheet properties. For example :-abp-properties(width:300px;height:250px;)
will select elements that have a corresponding CSS rule in a stylesheet which sets the width
and height
to the values 300px
and 250px
respectively. Property names are matched case-insensitively. Furthermore, wildcards can be used so that :-abp-properties(width:*px;height:250px;)
will match any width specified in pixels and a height of 250 pixels.
You can also use regular expressions by surrounding the properties expression with "/". For example, :-abp-properties(/width:30[2-8]px;height:250px;/)
will match widths between 302 and 308 pixels and a height of 250 pixels.
Note: The older syntax for the CSS property filters is deprecated and will be automatically converted to the new format . The syntax to select the style properties remain the same. For example, [-abp-properties='width:300px;height:250px;']
will be converted to :-abp-properties(width:300px;height:250px;)
.
:-abp-properties()
will also select elements using the style properties found in their pseudo-elements, like ::before
and ::after
. For example, :-abp-properties(content:'Advertisment')
will match elements where the string Advertisment is found in either their ::before
or ::after
pseudo element.
:-abp-has()
:-abp-has(selector)
will select elements based on their content. For example :-abp-has(> div > a.advertiser)
will select elements that contain as a direct descendant a <div>
that contains an <a>
with the class advertiser
. The inner selector can be relative to the element scope, and can use any of the pseudo-selectors, including :-abp-has()
and will determine whether the selection will occur.
:-abp-contains()
:-abp-contains(text)
will select elements based on their text content. For example, div.sidebar > span:-abp-contains(Advertisment)
will select the <span>
elements within a <div>
, with a class of sidebar
that contains the word "Advertisment". In practice, you'd want to combine this with a :-abp-has()
to select the outer container — something like div.sidebar > div:-abp-has(span:-abp-contains(Advertisment))
to select the container that would contain an advertisement label.
Exception rules
Exception rules can disable existing rules on particular domains. These are mostly
useful to filter subscription authors who are extending another filter subscription that they
cannot change. For example, the rule ##.textad
can be
disabled on example.com
using the exception rule
example.com#@#.textad
. The combination of these two
rules has exactly the same effect as the single rule
~example.com##.textad
. It is recommended that you use
exception rules only when you cannot change an overly general element hiding rule, in all the
other cases limiting this rule to the necessary domains is preferable.
These exceptions will be applied to advanced pseudo-selector rules as well.
Generic / Specific filters
With the $generichide
and $genericblock
filter options the distinction between generic and specific filters becomes important.
We classify a filter to be specific if it matches one or more domains or matches a sitekey. If a filter has no domains specified (or only domain exceptions) and no sitekey then it counts as generic. For example, example.com##.textad
is a specific filter, whereas both ##.textad
and ~example.com##.textad
are generic.
Note that with blocking rules the domain must be specified under the $domain option for them to be considered specific. For example, ||example.com^
is considered generic whereas */ads/*$domain=example.com
is site-specific.
Implementing a sitekey on the server
For a sitekey-restricted filter to apply, a webpage needs to return base64-encoded versions of the public key and a signature which Adblock Plus can validate. Currently, this means including them in both the HTTP response header (X-Adblock-Key: abcdpublickeydcba_abcdsignaturedcba
) and the root tag of the document (<html data-adblockkey="abcdpublickeydcba_abcdsignaturedcba">
).
First you need to create a private RSA key (preferably 512 bit to keep the transfer volume low) and then a DER representation of the public key.
The data used for creating the signature is a concatenated list of request variables (namely URI, host and user agent) separated by the NUL
character "\0". For example:
/index.html?q=foo\0www.example.com\0Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0
Finally, generate the signature for this string by using the signature algorithm SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE (default when using OpenSSL).