This page documents the assets.json schema that serves as the master registry for all filter lists and internal assets in uBlock Origin, the diff-patch update mechanism used for incremental updates, how assets.dev.json is used during development, and how to register a new filter list.
For how assets.js fetches, caches, and passes compiled filter data to the filtering engines at runtime, see page 3.4. For how MV3 rulesets reference filter sources at build time, see page 10.2.
assets/assets.json is the single source of truth for which assets the extension knows about. It is consumed by assets.js (the asset management layer in the background page) on every startup and update cycle. Every filter list shown in the dashboard's "Filter lists" pane originates from an entry in this file.
The file is itself a managed asset: its own entry at key "assets.json" points to CDN mirrors that can serve a newer version of the registry, allowing the list of available filter lists to be updated independently of the extension itself.
Asset registry flow:
Sources: assets/assets.json1-15 src/js/diff-updater.js183-264
Each top-level key in assets.json is a string asset ID (e.g. "ublock-filters", "easylist", "assets.json"). The value is an object with the fields described below.
| Field | Type | Required | Description |
|---|---|---|---|
content | "internal" | "filters" | Yes | "internal" marks non-filter assets (e.g. the registry itself, public_suffix_list.dat). "filters" marks assets that contribute filter rules. |
group | string | No | Top-level grouping category in the dashboard UI. See group values below. |
group2 | string | No | Secondary sub-grouping within a group (e.g. "cookies", "social" inside "annoyances"). |
parent | string | null | No | Display name of a logical parent group for UI nesting. |
title | string | Yes | Human-readable name shown in the filter list UI. |
tags | string | No | Space-separated keywords used by the UI search function. |
lang | string | No | Space-separated BCP 47 language codes. Used to highlight region-relevant lists. |
off | true | No | If present and true, the list is disabled by default. Absent means enabled. |
preferred | true | No | Marks the preferred list when multiple lists cover the same category. |
ua | "mobile" | No | User-agent hint. Indicates the list is primarily for mobile browsers. |
updateAfter | number | No | Minimum hours between update checks for this asset. Overrides the global default. |
contentURL | string | string[] | Yes | Canonical URL(s) for fetching the asset. Tried in order; first success wins. Local paths (assets/...) are also valid as fallbacks. |
cdnURLs | string[] | null | No | CDN mirror URLs tried in random order (for load distribution). Setting to null explicitly disables CDN fetching for an entry. |
patchURLs | string[] | No | Base URL prefixes for diff patch files. Enables incremental updates. See Diff-Update Mechanism below. |
supportURL | string | No | URL of the filter list's support/issue tracker. Shown in the dashboard. |
instructionURL | string | No | URL of additional usage instructions. Shown alongside certain lists. |
Sources: assets/assets.json1-996
Sources: assets/assets.json2-36 assets/assets.json38-60
The group field controls which section of the dashboard's filter list pane an entry appears in.
group value | Dashboard section | Example entries |
|---|---|---|
| (absent) | Default / no grouping | "assets.json", "public_suffix_list.dat" |
"default" | uBlock filters (always-on group) | "ublock-filters", "ublock-privacy" |
"ads" | Ads | "adguard-generic", "easylist" |
"privacy" | Privacy | "easyprivacy", "block-lan" |
"malware" | Malware domains | "urlhaus-1", "curben-phishing" |
"annoyances" | Annoyances | "ublock-annoyances", "adguard-cookies" |
"multipurpose" | Multipurpose | "dpollock-0", "plowe-0" |
"regions" | Regions & languages | "CHN-0", "DEU-0", "RUS-0" |
Sources: assets/assets.json38-996
When assets.js needs to fetch an asset, it follows this precedence:
Fetch diagram (asset update):
Sources: src/js/diff-updater.js183-264 assets/assets.json44-58
Multiple values in contentURL are tried in listed order. Multiple values in cdnURLs are tried in randomized order to distribute load across CDN providers. The function suffleArray in diff-updater.js implements this shuffle src/js/diff-updater.js33-41
Setting cdnURLs: null (as seen in "NLD-0") explicitly prevents any CDN fallback for that specific list.
Lists that include a patchURLs field support incremental diff-based updates. This avoids downloading the full filter list on every update cycle. The implementation lives in src/js/diff-updater.js, which is designed to run either inline or as a Web Worker.
A patch file hosted at a patchURLs base URL contains one or more named diff blocks:
diff name:<asset-name> checksum:<sha1-prefix> lines:<count>
<RCS-format diff lines>
diff name:<other-asset> checksum:<sha1-prefix> lines:<count>
<RCS-format diff lines>
Each block targets a specific named asset. The checksum is a SHA-1 prefix of the expected post-patch content, used to verify correctness.
The patch filename encodes its creation timestamp in the format YYYY.MM.DD.HHMM. The function expectedTimeFromPatch src/js/diff-updater.js55-66 parses this to determine whether the patch has been released yet, preventing unnecessary fetch attempts before the patch file exists on the CDN.
Diff-updater code entity map:
Sources: src/js/diff-updater.js55-264
| Function | Location | Purpose |
|---|---|---|
fetchAndApplyAllPatches | src/js/diff-updater.js223-264 | Top-level: fetch patch and apply to cached text |
fetchPatchDetails | src/js/diff-updater.js211-221 | Per-session cache of fetched patch metadata |
fetchPatchDetailsFromCDNs | src/js/diff-updater.js183-209 | Fetch the raw patch file from a CDN endpoint |
parsePatch | src/js/diff-updater.js68-105 | Parse multi-diff patch text into a Map keyed by asset name |
applyPatch | src/js/diff-updater.js107-144 | Apply RCS-format diff (a/d operations) to a text string |
applyPatchAndValidate | src/js/diff-updater.js156-181 | Apply patch, compute SHA-1 of result, compare to expected checksum |
expectedTimeFromPatch | src/js/diff-updater.js55-66 | Parse YYYY.MM.DD.HHMM timestamp from patch filename |
suffleArray | src/js/diff-updater.js33-41 | Fisher-Yates shuffle for CDN URL randomization |
After fetchAndApplyAllPatches completes, assetDetails.status is set to one of:
| Status | Meaning |
|---|---|
"updated" | Patch successfully applied and validated |
"nodiff" | Patch file present but no matching diff for this asset name |
"needtext" | Patch available but current text not in memory (full fetch needed) |
"nopatch-yet" | Patch timestamp is in the future; too early to fetch |
"nopatch" | Patch not found and sufficient time has passed (fall back to full fetch) |
"baddiff" (via error) | Patch apply failed |
"badchecksum" (via error) | Patch applied but SHA-1 mismatch |
Sources: src/js/diff-updater.js226-263
assets/assets.dev.json is a development-only variant of the registry. It is structurally identical to assets.json but its own "assets.json" entry's contentURL and cdnURLs point to assets.dev.json instead of assets.json:
When a development build loads assets.dev.json as its registry, subsequent auto-updates of the registry will also pull assets.dev.json, keeping the development environment self-consistent. This prevents a development build from accidentally pulling the production assets.json and overwriting development-specific entries.
Sources: assets/assets.dev.json1-15
The "ublock-filters" entry demonstrates all major fields:
Key observations:
contentURL lists three sources in descending preference: live GitHub Pages URL, local bundled minified copy, local full copy.cdnURLs provides CDN mirrors of the minified version.patchURLs enables diff updates; patches are fetched relative to these base URLs.off field → enabled by default.updateAfter → uses the global default update interval.Sources: assets/assets.json38-59
To add a new filter list to the registry, add a new entry to assets/assets.json (and mirror the addition to assets/assets.dev.json):
Choose a unique asset ID — conventionally a short string identifying the list origin and a numeric suffix (e.g. "mytopic-0").
Set content: "filters" — for any list that contributes filter rules.
Set group — pick the closest match from the group values table above.
Provide contentURL — at minimum one HTTPS URL to the raw filter list text. Provide a local assets/ path as a fallback if the list is bundled with the extension.
Optionally provide cdnURLs — list CDN mirrors for load distribution and reliability.
Set off: true if the list should be opt-in.
Set title, tags, and supportURL for the dashboard UI.
Optionally add patchURLs if the list host provides a compatible diff-patch service.
Minimal new entry:
Note: Adding a list to
assets.jsonmakes it available in the UI. It does not automatically enable it. Theoff: truefield controls the default state. Users can then enable it from the Filter lists pane in the dashboard (see page 7.2).
Sources: assets/assets.json170-188 assets/assets.json572-580
uBOLite (MV3) uses a parallel registry: platform/mv3/rulesets.json. It serves the same conceptual role but with a different schema suited to pre-compiled DNR rulesets. The key differences are:
| Field | assets.json (MV2) | rulesets.json (MV3) |
|---|---|---|
| URL field name | contentURL | urls |
| CDN mirrors | cdnURLs | (absent — compiled at build time) |
| Patch updates | patchURLs | (absent — DNR rulesets are static) |
| Enabled default | absent = enabled, off: true = disabled | "enabled": true/false |
| Platform exclusions | (absent) | excludedPlatforms: ["safari"] |
| Trusted flag | (absent) | "trusted": true |
For the complete MV3 ruleset compilation pipeline, see page 10.2.
Sources: platform/mv3/rulesets.json1-648 assets/assets.json38-60
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.