Streambert Ad Tracker Blocking Network Requests: A Deep Dive into the Architecture

Streambert blocks ads and trackers using Electron's webRequest API in the main process, employing a static host filter list combined with session-level interception and real-time statistics reporting to prevent advertising and analytics traffic from reaching the renderer.

Streambert is an Electron-based media streaming client designed to strip advertising and tracking traffic before it ever reaches the webview. According to the truelockmc/streambert source code, the blocking logic operates entirely within the privileged main process across three tightly coupled layers: network filtering, session management, and statistics reporting.

Static Block List Definition

The foundation of Streambert's ad blocking capability is the BLOCKED_HOSTS array defined in [index.js](https://github.com/truelockmc/streambert/blob/main/index.js#L46-L99). This static list contains approximately 50+ URL patterns targeting common analytics and advertising domains.

const BLOCKED_HOSTS = [
  "*://www.google-analytics.com/*",
  "*://analytics.google.com/*",
  "*://googletagmanager.com/*",
  // … additional patterns
];

This array is initialized once at application startup and serves as the primary filter for the Electron webRequest API. Because BLOCKED_HOSTS is exported as a plain JavaScript array, it can be extended at runtime without requiring a rebuild of the application.

Session-Level Request Interception

The setupSession function in [index.js](https://github.com/truelockmc/streambert/blob/main/index.js#L8-L85) creates two persistent Electron sessions: persist:player and persist:trailer. Each session receives different filtering rules based on its purpose.

Trailer Session Blocking

For trailer content, only the ad blocking rules apply:

trailerSession.webRequest.onBeforeRequest(
  { urls: BLOCKED_HOSTS },
  (_, cb) => cb({ cancel: true })
);

Player Session Blocking

The player session combines ad blocking with media URL interception for formats like *.m3u8 and *.vtt. When a request matches a blocked host, it is cancelled immediately; otherwise, media URLs are forwarded to the renderer via IPC:

playerSession.webRequest.onBeforeRequest(
  { urls: [...BLOCKED_HOSTS, ...MEDIA_URLS] },
  (details, callback) => {
    // Cancel if blocked, forward if media
  }
);

This architecture ensures that advertising and tracking scripts never execute in the renderer, while legitimate media streams flow through to the player components.

Recording and Persisting Blocked Requests

When the onBeforeRequest handler cancels a request, it triggers recordBlockedRequest(url) in [src/ipc/blockStats.js](https://github.com/truelockmc/streambert/blob/main/src/ipc/blockStats.js) (lines 48-82). This function:

  1. Parses the hostname from the blocked URL
  2. Updates in-memory counters (total and per-domain)
  3. Debounces IPC updates to the UI (every 250ms)
  4. Debounces disk persistence (every 3 seconds to minimize I/O overhead)

The statistics are stored in blockStats.json within the user's data directory, ensuring counts survive application restarts.

UI Integration and Real-Time Reporting

The renderer process receives updates through the useBlockedStats hook in [src/utils/useBlockedStats.js](https://github.com/truelockmc/streambert/blob/main/src/utils/useBlockedStats.js). This React hook listens to the blocked-stats-update IPC channel and merges incremental batches into component state.

The [BlockedStatsModal.jsx](https://github.com/truelockmc/streambert/blob/main/src/components/BlockedStatsModal.jsx) component displays both the aggregate blocked count and a per-domain breakdown, providing users with transparent visibility into exactly how many ad and tracker requests have been prevented.

Practical Implementation Examples

Adding Custom Hosts to the Block List

Extend the blocking capabilities at runtime by pushing new patterns to the exported array:

// After app is ready
const { session } = require('electron');
const { BLOCKED_HOSTS } = require('../index');

BLOCKED_HOSTS.push('*://ads.example.com/*');

const playerSession = session.fromPartition('persist:player');
playerSession.webRequest.onBeforeRequest(
  { urls: BLOCKED_HOSTS },
  (_, cb) => cb({ cancel: true })
);

Accessing Statistics in the Renderer

Use the provided hook to display real-time blocking data:

import { useBlockedStats } from '../utils/useBlockedStats';

export default function StatsPanel() {
  const { total, domains } = useBlockedStats();
  
  return (
    <div>
      <strong>Blocked:</strong> {total}
      <ul>
        {Object.entries(domains).map(([domain, count]) => (
          <li key={domain}>{domain}: {count}</li>
        ))}
      </ul>
    </div>
  );
}

Resetting Block Statistics

Clear accumulated data from the main process:

const blockStats = require('./src/ipc/blockStats');
const fs = require('fs');
const path = require('path');
const { app } = require('electron');

// Option 1: Reload from disk (clears memory)
blockStats.loadBlockStats();

// Option 2: Delete persistence file
fs.unlinkSync(path.join(app.getPath('userData'), 'blockStats.json'));

Summary

  • Static filtering: The BLOCKED_HOSTS array in index.js defines URL patterns for known ad and analytics domains.
  • Session isolation: Separate Electron sessions (persist:player, persist:trailer) receive appropriate filtering rules via setupSession.
  • Request cancellation: The webRequest.onBeforeRequest API cancels matching requests before they reach the renderer.
  • Statistics tracking: The recordBlockedRequest function in blockStats.js maintains counters with debounced IPC updates (250ms) and disk writes (3s).
  • UI transparency: The useBlockedStats hook streams data to React components, displaying total and per-domain blocked counts.

Frequently Asked Questions

How does Streambert prevent ads from loading without breaking video content?

Streambert distinguishes between ad/tracker requests and legitimate media streams by using separate URL pattern arrays. The BLOCKED_HOSTS filter blocks analytics and advertising domains, while MEDIA_URLS (containing patterns like *.m3u8 and *.vtt) allows video manifests and subtitles to pass through. This selective filtering happens in the main process before any content reaches the renderer.

Can users customize which domains are blocked in Streambert?

Yes. Because BLOCKED_HOSTS is exported as a mutable array from index.js, users or extensions can push additional patterns at runtime. After modifying the array, the new patterns can be applied to existing sessions by re-registering the onBeforeRequest handler with the updated URL list.

Where does Streambert store the ad blocking statistics?

Block statistics are persisted to a JSON file named blockStats.json located in the Electron user data directory (retrieved via app.getPath('userData')). The data includes total blocked requests and a breakdown by domain, allowing the counter to survive application restarts.

What is the performance impact of Streambert's request interception?

The implementation minimizes overhead through strategic debouncing. While request interception itself happens synchronously for every network call, statistics reporting uses a 250ms debounce for IPC updates to the renderer and a 3-second debounce for disk writes. This ensures that heavy media playback does not trigger excessive I/O operations or UI re-renders.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →