npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adguard/filters-downloader

v2.4.4

Published

Downloads filter source files

Readme

@adguard/filters-downloader

A library that downloads filter list source files by resolving preprocessor directives. It handles conditional compilation, file inclusion, checksum validation, and differential (patch-based) filter updates. The library works in both Node.js and browser environments.

Table of Contents

Overview

Filter lists used by ad blockers are often composed of multiple source files and contain platform-specific rules gated behind preprocessor directives. This library takes a filter URL (or an array of rules) and produces a flat, ready-to-use list of rules by:

  • Resolving !#include directives — fetches and inlines referenced files
  • Resolving !#if/!#else/!#endif directives — includes or excludes rule blocks based on caller-provided condition constants
  • Validating checksums — optionally verifies the MD5 checksum embedded in the filter header
  • Applying differential updates — when a previously downloaded raw filter is supplied, attempts to update it via a binary patch instead of a full re-download

Installation

pnpm add @adguard/filters-downloader
# or
npm install @adguard/filters-downloader
# or
yarn add @adguard/filters-downloader

Importing

Node.js (CommonJS / ESM):

import { FiltersDownloader } from '@adguard/filters-downloader';

Browser (ESM):

import { FiltersDownloader } from '@adguard/filters-downloader/browser';

Key Concepts

Condition constants (DefinedExpressions)

When compiling a filter, you pass a DefinedExpressions object that declares which platform constants are true for the current ad blocker. The library evaluates !#if expressions against these constants and includes only the rules that apply to your platform.

Recognized constants:

| Constant | Description | | -------------------------- | ----------------------------------- | | adguard | AdGuard product (any) | | adguard_ext_chromium | AdGuard for Chromium-based browsers | | adguard_ext_chromium_mv3 | AdGuard for Chromium MV3 | | adguard_ext_firefox | AdGuard for Firefox | | adguard_ext_edge | AdGuard for Edge | | adguard_ext_safari | AdGuard for Safari | | adguard_ext_opera | AdGuard for Opera | | adguard_ext_android_cb | AdGuard for Android Content Blocker |

Any constant not present in the DefinedExpressions object is treated as false. See the AdGuard conditions directive docs for the full list of recognized constants.

Preprocessor directives

Conditional blocks

!#if (adguard && !adguard_ext_safari)
||example.org^$third-party
!#endif
!#if adguard_ext_firefox
!#include https://example.org/path/firefox-rules.txt
!#else
!#include https://example.org/path/other-rules.txt
!#endif
  • !#if / !#else / !#endif delimit conditional blocks.
  • Conditions support &&, ||, !, and parentheses.
  • Only the block whose condition evaluates to true is included in the output.

File inclusion

!
! Valid (same origin, absolute path):
!#include https://example.org/path/includedfile.txt
!
! Valid (relative path):
!#include /includedfile.txt
!#include ../path2/includedfile.txt
!
! Invalid (different origin — rejected):
!#include https://example.com/path/includedfile.txt

!#include fetches the referenced file and splices its rules into the output at that position. Included files may themselves contain directives. Only files from the same origin as the parent filter are permitted.

Checksums

A filter file may embed an MD5 checksum in its header (e.g. ! Checksum: <base64-md5>). When validateChecksum: true is passed, the library verifies the checksum after downloading. Use validateChecksumStrict: true to treat a missing checksum as an error.

Differential updates

downloadWithRaw keeps the raw (uncompiled) filter text alongside the compiled output. On subsequent calls, passing the previously stored rawFilter lets the library apply a binary patch (if the server provides one) instead of downloading the entire filter again, reducing bandwidth usage.

API Reference

All methods are on the FiltersDownloader object.

download(url, definedExpressions?, options?)

Downloads a filter from url, resolves all directives, and returns the compiled rules as a string[].

const rules: string[] = await FiltersDownloader.download(
    'https://example.org/filter.txt',
    { adguard: true, adguard_ext_firefox: true },
);

Options (LegacyDownloadOptions):

| Option | Type | Default | Description | | ------------------------ | --------- | ------- | -------------------------------------- | | validateChecksum | boolean | false | Verify the embedded MD5 checksum | | validateChecksumStrict | boolean | false | Error if no checksum is present | | allowEmptyResponse | boolean | false | Allow downloading an empty filter file |

By default an empty top-level response throws 'Response is empty'. Included files may be empty regardless of this option.


downloadWithRaw(url, options)

Downloads a filter and returns both the compiled rules and the raw (uncompiled) filter text. On subsequent calls, supply the stored rawFilter so the library can apply a differential patch instead of a full re-download.

// First download — no previous raw filter
const { filter, rawFilter } = await FiltersDownloader.downloadWithRaw(
    'https://example.org/filter.txt',
    { definedExpressions: { adguard: true } },
);

// Store rawFilter and use it next time
const { filter: updated, rawFilter: newRaw, isPatchUpdateFailed } =
    await FiltersDownloader.downloadWithRaw(
        'https://example.org/filter.txt',
        {
            rawFilter,           // previously stored raw filter
            definedExpressions: { adguard: true },
        },
    );

Returns (DownloadResult):

| Field | Type | Description | | --------------------- | ---------------------- | ------------------------------------------------------------------------------ | | filter | string[] | Compiled rules | | rawFilter | string | Raw filter text before directive resolution | | isPatchUpdateFailed | boolean \| undefined | true if a patch was attempted but failed (full re-download was used instead) | | headers | object \| undefined | HTTP response headers from the filter download (see below) |

headers shape:

| Field | Type | Description | | -------------- | --------------------- | ----------------------------------------------------- | | lastModified | string \| undefined | The value of the Last-Modified HTTP response header |

Note: headers.lastModified can be used as a fallback update timestamp when filter metadata does not contain a TimeUpdated field.

Options (DownloadWithRawOptions):

| Option | Type | Default | Description | | ------------------------ | --------------------- | ----------- | ----------------------------------------------- | | force | boolean | false | Skip patch attempt and force a full re-download | | rawFilter | string | undefined | Previously stored raw filter to diff against | | definedExpressions | DefinedExpressions | undefined | Condition constants for directive resolution | | validateChecksum | boolean | false | Verify the embedded MD5 checksum | | validateChecksumStrict | boolean | false | Error if no checksum is present | | allowEmptyResponse | boolean | false | Allow an empty filter response | | verbose | boolean | false | Enable detailed logging for troubleshooting |


compile(rules, filterOrigin?, definedExpressions?)

Resolves all directives in an already-fetched string[] of rules. Useful when you have the raw lines in memory and do not need an HTTP download.

const rawRules = [
    '!#if adguard_ext_firefox',
    '||firefox-only.example.org^',
    '!#endif',
    '||example.org^',
];

const compiled: string[] = await FiltersDownloader.compile(
    rawRules,
    'https://example.org/filter.txt', // used to resolve relative !#include paths
    { adguard_ext_firefox: true },
);
// → ['||firefox-only.example.org^', '||example.org^']

resolveConditions(rules, definedExpressions?)

Evaluates !#if / !#else / !#endif directives and returns a new string[] with non-matching blocks removed. Does not fetch !#include references.

const filtered = FiltersDownloader.resolveConditions(rules, { adguard: true });

resolveIncludes(rules, filterOrigin?, definedExpressions?)

Fetches and inlines all !#include references. Does not evaluate !#if conditions.

const expanded = await FiltersDownloader.resolveIncludes(
    rules,
    'https://example.org/filter.txt',
    { adguard: true },
);

getFilterUrlOrigin(url)

Returns the base directory URL of url (everything up to and including the last /). Used internally to resolve relative !#include paths.

FiltersDownloader.getFilterUrlOrigin('https://example.org/path/filter.txt');
// → 'https://example.org/path'

Documentation

Projects using FiltersDownloader