WebView Content Blockers

Add triggers to your Content Blocker

initialSettings: InAppWebViewSettings(contentBlockers: [
  ContentBlocker(
    trigger: ContentBlockerTrigger(
      urlFilter: ".*",
      resourceType: [
        ContentBlockerTriggerResourceType.IMAGE,
        ContentBlockerTriggerResourceType.STYLE_SHEET
      ],
      unlessDomain: ["example.com", "github.com", "pub.dev"]
    ),
    action: ContentBlockerAction(
      type: ContentBlockerActionType.BLOCK
    )
  )
]),


For deeper trigger customization, you can use the other properties of ContentBlockerTrigger :

  • urlFilterIsCaseSensitive: If the URL matching should be case-sensitive. By default, it is case insensitive.
  • resourceType: A list of “ContentBlockerTriggerResourceType” representing the resource types (how the browser intends to use the resource) that the rule should match. If not specified, the rule matches all resource types.
  • ifDomain: A list of strings matched to a URL’s domain; limits action to a list of specific domains. Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. It can’t be used with “unlessDomain”.
  • unlessDomain: A list of strings matched to a URL’s domain; acts on any site except domains in a provided list. Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. It can’t be used with “ifDomain”.
  • loadType: A list of “ContentBlockerTriggerLoadType” that can include one of two mutually exclusive values. If not specified, the rule matches all load types. “ContentBlockerTriggerLoadType.FIRST_PARTY” triggers only if the resource has the same scheme, domain, and port as the main page resource. “ContentBlockerTriggerLoadType.THIRD_PARTY” triggers if the resource isn’t from the same domain as the main page resource.
  • ifTopUrl: A list of strings matched to the entire main document URL; limits the action to a specific list of URL patterns. Values must be lowercase ASCII, or punycode for non-ASCII. It can’t be used with “unlessTopUrl”.
  • unlessTopUrl: An array of strings matched to the entire main document URL; acts on any site except URL patterns in the provided list. Values must be lowercase ASCII, or punycode for non-ASCII. It can’t be used with “ifTopUrl”.
  • loadContext: An array of strings that specify loading contexts.
  • ifFrameUrl: A list of regular expressions to match iframes URL against.


Add actions to your Content Blocker

initialSettings: InAppWebViewSettings(contentBlockers: [
  ContentBlocker(
    trigger: ContentBlockerTrigger(
      urlFilter: "https://flutter.dev/.*",
    ),
    action: ContentBlockerAction(
      type: ContentBlockerActionType.CSS_DISPLAY_NONE,
      selector: '.notification, .media, #developer-story'
    )
  )
]),


Valid types are:

  • BLOCK: Stops loading of the resource. If the resource was cached, the cache is ignored.
  • BLOCK_COOKIES: Strips cookies from the header before sending it to the server. This only blocks cookies otherwise acceptable to WebView’s privacy policy. Combining with “IGNORE_PREVIOUS_RULES” doesn’t override the browser’s privacy settings.
  • CSS_DISPLAY_NONE: Hides elements of the page based on a CSS selector. A selector field contains the selector list. Any matching element has its display property set to none, which hides it.
  • MAKE_HTTPS: Changes a URL from http to https. URLs with a specified (nondefault) port and links using other protocols are unaffected.
  • IGNORE_PREVIOUS_RULES: Ignores previously triggered actions.


Creating a simple Ad Blocker

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (!kIsWeb &&
      kDebugMode &&
      defaultTargetPlatform == TargetPlatform.android) {
    await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
  }
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final GlobalKey webViewKey = GlobalKey();

  // list of Ad URL filters to be used to block ads loading.
  final adUrlFilters = [
    ".*.doubleclick.net/.*",
    ".*.ads.pubmatic.com/.*",
    ".*.googlesyndication.com/.*",
    ".*.google-analytics.com/.*",
    ".*.adservice.google.*/.*",
    ".*.adbrite.com/.*",
    ".*.exponential.com/.*",
    ".*.quantserve.com/.*",
    ".*.scorecardresearch.com/.*",
    ".*.zedo.com/.*",
    ".*.adsafeprotected.com/.*",
    ".*.teads.tv/.*",
    ".*.outbrain.com/.*"
  ];

  final List<ContentBlocker> contentBlockers = [];
  var contentBlockerEnabled = true;

  InAppWebViewController? webViewController;

  @override
  void initState() {
    super.initState();

    // for each Ad URL filter, add a Content Blocker to block its loading.
    for (final adUrlFilter in adUrlFilters) {
      contentBlockers.add(ContentBlocker(
          trigger: ContentBlockerTrigger(
            urlFilter: adUrlFilter,
          ),
          action: ContentBlockerAction(
            type: ContentBlockerActionType.BLOCK,
          )));
    }

    // apply the "display: none" style to some HTML elements
    contentBlockers.add(ContentBlocker(
        trigger: ContentBlockerTrigger(
          urlFilter: ".*",
        ),
        action: ContentBlockerAction(
            type: ContentBlockerActionType.CSS_DISPLAY_NONE,
            selector: ".banner, .banners, .ads, .ad, .advert")));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Ads Content Blocker"),
          actions: [
            TextButton(
              onPressed: () async {
                contentBlockerEnabled = !contentBlockerEnabled;
                if (contentBlockerEnabled) {
                  await webViewController?.setSettings(
                      settings: InAppWebViewSettings(
                          contentBlockers: contentBlockers));
                } else {
                  await webViewController?.setSettings(
                      settings: InAppWebViewSettings(contentBlockers: []));
                }
                webViewController?.reload();

                setState(() {});
              },
              style: TextButton.styleFrom(foregroundColor: Colors.white),
              child: Text(contentBlockerEnabled ? 'Disable' : 'Enable'),
            )
          ],
        ),
        body: SafeArea(
            child: Column(children: <Widget>[
          Expanded(
            child: Stack(
              children: [
                InAppWebView(
                  key: webViewKey,
                  initialUrlRequest:
                      URLRequest(url: WebUri('https://www.tomshardware.com/')),
                  initialSettings:
                      InAppWebViewSettings(contentBlockers: contentBlockers),
                  onWebViewCreated: (controller) {
                    webViewController = controller;
                  },
                ),
              ],
            ),
          ),
        ])));
  }
}