This is the thirty-first post in an ongoing series highlighting privacy and adblocking innovations in iBrowe. This update features work by Anton Lazarev (Senior Adblock Research Engineer), Stephen Heaps (Senior Software Engineer, iOS), and Pete Snyder (Principal Privacy Researcher), with write-up by Shivan Kaul Sahib (Lead for Privacy Engineering).


📋 Overview

Starting with iBrowe 1.73 on all platforms (Desktop, Android, and iOS), iBrowe introduces procedural cosmetic filtering—a powerful enhancement to our existing adblocking engine. Procedural filtering augments traditional CSS‐based hide‐rules by allowing dynamic, content-aware matching of page elements. As a result, iBrowe will (1) block a broader range of intrusive ads that evade static selectors; (2) reduce site breakage caused by overly broad rules; and (3) precisely target unwanted content based on keywords, element properties, HTML structure, and more. Combined with network-level adblocking, this means fewer blank spaces, fewer false positives, and an overall cleaner, faster browsing experience. 🌐✨


🔍 1. Why Procedural Filtering Matters

1.1 Limitations of Traditional CSS Selectors

  • Declarative Approach: Standard cosmetic filters rely on CSS selectors (e.g., .ad-banner, .sponsored-post) to hide elements. While effective for clearly labeled ads, many sites obfuscate class names or inject ads that mimic site formatting.
  • Auto-Generated Classes: Modern frameworks (React, Angular) often produce randomized class names. Static rules quickly become outdated, causing (a) missed ads, or (b) unintended hiding of legitimate content.
  • Context Insensitivity: CSS selectors cannot distinguish between two blocks with identical class names—one an ad, one user content. This leads to site breakage or incomplete ad removal.

1.2 The Power of Procedural Matching

Procedural (imperative) filters let iBrowe evaluate an element’s:

  • Text Content: Hide elements containing specific keywords (e.g., “Buy Now,” “Sponsored,” “Advertisement”). ✏️
  • Ancestor/Descendant Relations: Target an ad only when nested under a known ad container, while preserving similarly styled native content. 🧩
  • Element Dimensions: Block off-canvas popups or unusually large fixed banners based on width/height thresholds. 📏
  • Attribute Patterns: Match href, src, or data-ad attributes with dynamic patterns (e.g., contains("adserver")). 🔍
  • Sibling/Position Rules: Hide banners that always appear as the nth child of a specific container. 👉

By combining multiple conditions in a procedural rule, iBrowe can accurately pinpoint intrusive ads even when site authors intentionally disguise them.


🔨 2. How Procedural Filtering Works in iBrowe

2.1 Procedural Operators

iBrowe supports the most widely used procedural operators from filter-list standards:

Operator Description
:has-text("…") Matches elements containing the exact text string (case-insensitive).
:has-length(>N) Matches elements whose text length exceeds N characters (useful against auto-generated links).
:xpath("…") Targets elements via an XPath expression, enabling complex structural matching.
:matches-css("*") Applies when certain computed CSS properties (e.g., position: fixed, z-index: 9999) match.
:nth-child(n) Selects the nth child under a parent element, useful for nested ad containers.
:attr("…", "*") Matches when an attribute (e.g., data-ad, aria-label) contains a substring.

💡 Tip: Combine multiple operators with , or logical AND syntax to fine-tune your rules.

2.2 Sample Procedural Rule Syntax

  1. Block a “Subscribe Now” pop-in
    ##div:has-text("Subscribe Now"):has-css("position", "fixed"):has-length(>50)