BlinkGTK Settings API Tutorial (Python/PyGObject)

Last Updated: 2026-10-21
Target Version: BlinkGTK 1.2.5 or later
Level: Beginner to Intermediate
Language: 日本語 | English


Table of Contents

  1. Introduction
  2. PyGObject Setup
  3. Basic Usage
  4. Settings API Details
  5. Pythonic Patterns
  6. Practical Examples
  7. Migrating from WebKitGTK

Introduction

This tutorial shows how to use BlinkGTK settings (JavaScript, images, local storage, User-Agent and font size) from Python with PyGObject.
Every complete program here was run and checked with BlinkGTK 1.2.5 (Chromium 156).

What You Will Learn

If you used code from an earlier version of this tutorial

The code previously on this page used names that do not exist, so it did not work. Replace it as follows.

Earlier code (does not exist) Correct code
import blink_gtk / blink_gtk.init() from gi.repository import BlinkGTK / BlinkGTK.gtk_init(sys.argv[:1])
app.run() BlinkGTK.gtk_application_run(app)
blink_gtk.shutdown() BlinkGTK.gtk_shutdown()
set_enable_javascript() / get_enable_javascript() set_javascript_enabled() / get_javascript_enabled()
set_auto_load_images() / get_auto_load_images() set_images_enabled() / get_images_enabled()
set_enable_local_storage() / get_enable_local_storage() set_local_storage_enabled() / get_local_storage_enabled()

Prerequisites


PyGObject Setup

Installation

BlinkGTK 1.2.5 or later and a Wayland desktop are required (versions up to 1.2.4 cannot start from Python; X11 is not supported).

Fedora:

sudo dnf install python3-gobject gtk4 blinkgtk-bin blinkgtk-bin-gir

Debian / Ubuntu:

sudo apt install python3-gi gir1.2-gtk-4.0
# Install BlinkGTK and its introspection data from the downloaded DEB files (there is no APT repository)
sudo apt install ./libblinkgtk-0.1-0_<version>-1_amd64.deb ./gir1.2-blinkgtk-0.1_<version>-1_amd64.deb

Your First Program

The smallest program, from initialization to showing a window, is explained in the Python tutorial.
The programs on this page follow the same sequence (BlinkGTK.gtk_init() → BlinkGTK.gtk_application_run() → BlinkGTK.gtk_shutdown()).

Always run them through blinkgtk-run (for example, save as settings.py and run blinkgtk-run python3 settings.py). Without it, the program aborts when it opens an HTTPS page (why).


Basic Usage

JavaScript Control

#!/usr/bin/env python3
"""Open a page with JavaScript disabled"""
import sys

import gi

gi.require_version("Gtk", "4.0")
gi.require_version("BlinkGTK", "0.1")
from gi.repository import BlinkGTK, Gtk  # noqa: E402


def on_activate(app, url):
    window = Gtk.ApplicationWindow(application=app, title="JavaScript Control")
    window.set_default_size(800, 600)

    web_view = BlinkGTK.WebView.new()
    window.set_child(web_view)

    # Apply settings before loading a page
    web_view.set_javascript_enabled(False)
    print(f"JavaScript: {'enabled' if web_view.get_javascript_enabled() else 'disabled'}", flush=True)

    # Show the page title in the window (a page whose script changes its title shows the difference)
    web_view.connect("title-changed", lambda v: window.set_title(v.get_title() or ""))

    window.present()
    web_view.load_uri(url)


def main():
    url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com/"
    ok, _argv = BlinkGTK.gtk_init(sys.argv[:1])
    if not ok:
        print("Could not initialize BlinkGTK", file=sys.stderr)
        return 1
    app = Gtk.Application(application_id="org.example.JavaScriptControl")
    app.connect("activate", on_activate, url)
    rc = BlinkGTK.gtk_application_run(app)
    BlinkGTK.gtk_shutdown()
    return rc


if __name__ == "__main__":
    sys.exit(main())

Open a page whose script rewrites its title: the title stays unchanged, which shows that the script did not run.

Changing the User-Agent

#!/usr/bin/env python3
"""Open a page with a custom User-Agent"""
import sys

import gi

gi.require_version("Gtk", "4.0")
gi.require_version("BlinkGTK", "0.1")
from gi.repository import BlinkGTK, Gtk  # noqa: E402


def on_activate(app, url):
    window = Gtk.ApplicationWindow(application=app, title="User-Agent")
    window.set_default_size(800, 600)

    web_view = BlinkGTK.WebView.new()
    window.set_child(web_view)

    print(f"Before: {web_view.get_user_agent()}", flush=True)  # None when not changed
    web_view.set_user_agent("MyPythonApp/1.0 (BlinkGTK)")
    print(f"After: {web_view.get_user_agent()}", flush=True)

    web_view.connect("title-changed", lambda v: window.set_title(v.get_title() or ""))
    window.present()
    web_view.load_uri(url)


def main():
    url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com/"
    ok, _argv = BlinkGTK.gtk_init(sys.argv[:1])
    if not ok:
        print("Could not initialize BlinkGTK", file=sys.stderr)
        return 1
    app = Gtk.Application(application_id="org.example.UserAgent")
    app.connect("activate", on_activate, url)
    rc = BlinkGTK.gtk_application_run(app)
    BlinkGTK.gtk_shutdown()
    return rc


if __name__ == "__main__":
    sys.exit(main())

Note: The User-Agent you set is sent to pages loaded afterwards and to pages reloaded with reload() (the HTTP header and navigator.userAgent). Up to 1.2.4 it was not applied to pages opened with load_uri().


Settings API Details

When to Change Settings

Overview

Setting Set Get Default
JavaScript set_javascript_enabled(bool) get_javascript_enabled() True
Loading images set_images_enabled(bool) get_images_enabled() True
Local storage set_local_storage_enabled(bool) get_local_storage_enabled() True
User-Agent set_user_agent(str or None) get_user_agent() None (Chromium's default is used)
Default font size (CSS px) set_default_font_size(int) get_default_font_size() 16
Minimum font size (CSS px) set_minimum_font_size(int) get_minimum_font_size() 0 (no minimum)
Font family set_font_family(generic, script, family) get_font_family(generic, script) None when not set

1. JavaScript Control

web_view.set_javascript_enabled(False)   # disable
web_view.set_javascript_enabled(True)    # enable

js_enabled = web_view.get_javascript_enabled()
print(f"JavaScript: {'enabled' if js_enabled else 'disabled'}")

2. User-Agent Control

web_view.set_user_agent("MyApp/1.0 (BlinkGTK)")
print(web_view.get_user_agent())   # "MyApp/1.0 (BlinkGTK)"

web_view.set_user_agent(None)      # clear the setting
print(web_view.get_user_agent())   # None

get_user_agent() returns the string set with set_user_agent(), or None when nothing is set.
The setting applies to pages loaded afterwards and to pages you reload() (see the note above).

3. Image Loading Control

web_view.set_images_enabled(False)   # do not load images
web_view.set_images_enabled(True)    # load images

images_enabled = web_view.get_images_enabled()
print(f"Image loading: {'enabled' if images_enabled else 'disabled'}")

4. Local Storage Control

web_view.set_local_storage_enabled(False)   # do not allow localStorage
web_view.set_local_storage_enabled(True)

storage_enabled = web_view.get_local_storage_enabled()
print(f"Local storage: {'enabled' if storage_enabled else 'disabled'}")

5. Font Size and Font Family

web_view.set_default_font_size(24)   # body text of pages that set no font size becomes 24px
web_view.set_minimum_font_size(12)   # text smaller than 12px is shown at 12px

# Change the font used for serif. Passing None as script sets both Japanese and Latin text
web_view.set_font_family(BlinkGTK.FontGeneric.SERIF, None, "Noto Serif CJK JP")
print(web_view.get_font_family(BlinkGTK.FontGeneric.SERIF, "Jpan"))

Pythonic Patterns

1. A Class That Handles Settings Together

from typing import Any


class BrowserSettings:
    """Handle the settings of a WebView together"""

    def __init__(self, web_view: BlinkGTK.WebView):
        self.web_view = web_view

    def get_settings(self) -> dict[str, Any]:
        return {
            "javascript": self.web_view.get_javascript_enabled(),
            "images": self.web_view.get_images_enabled(),
            "storage": self.web_view.get_local_storage_enabled(),
            "font_size": self.web_view.get_default_font_size(),
            "user_agent": self.web_view.get_user_agent(),  # None when not changed
        }

    def apply_settings(self, settings: dict[str, Any]) -> None:
        if "javascript" in settings:
            self.web_view.set_javascript_enabled(settings["javascript"])
        if "images" in settings:
            self.web_view.set_images_enabled(settings["images"])
        if "storage" in settings:
            self.web_view.set_local_storage_enabled(settings["storage"])
        if "font_size" in settings:
            self.web_view.set_default_font_size(settings["font_size"])
        if "user_agent" in settings:
            self.web_view.set_user_agent(settings["user_agent"])


# Usage (before loading a page)
settings = BrowserSettings(web_view)
settings.apply_settings({"images": False, "font_size": 20})
print(settings.get_settings())

2. Using Properties

class BrowserWindow(Gtk.ApplicationWindow):
    """A window that reads and writes settings as Python properties"""

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.web_view = BlinkGTK.WebView.new()
        self.set_child(self.web_view)

    @property
    def javascript_enabled(self) -> bool:
        return self.web_view.get_javascript_enabled()

    @javascript_enabled.setter
    def javascript_enabled(self, enabled: bool) -> None:
        self.web_view.set_javascript_enabled(enabled)

    @property
    def images_enabled(self) -> bool:
        return self.web_view.get_images_enabled()

    @images_enabled.setter
    def images_enabled(self, enabled: bool) -> None:
        self.web_view.set_images_enabled(enabled)


# Usage (inside the activate handler)
window = BrowserWindow(application=app)
window.javascript_enabled = False
window.images_enabled = False
print(f"JavaScript: {window.javascript_enabled}")

3. About Changing Settings Temporarily

Do not change settings in a with block and restore them when the block ends (a context manager).
load_uri() returns immediately and the load continues afterwards, so if the settings are restored when the block ends, it is undetermined which settings the page is loaded with.
To use different settings for a load, set them and then call load_uri() or reload().


Practical Examples

Example 1: Data Saver Mode

#!/usr/bin/env python3
"""A browser with a data saver mode switch (turns off JavaScript and images)"""
import sys

import gi

gi.require_version("Gtk", "4.0")
gi.require_version("BlinkGTK", "0.1")
from gi.repository import BlinkGTK, Gtk  # noqa: E402


class DataSaverBrowser(Gtk.ApplicationWindow):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.set_title("Data Saver Browser")
        self.set_default_size(800, 600)

        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        for side in ("start", "end", "top", "bottom"):
            getattr(hbox, f"set_margin_{side}")(10)
        hbox.append(Gtk.Label(label="Data saver mode:"))
        self.data_saver_switch = Gtk.Switch()
        self.data_saver_switch.connect("notify::active", self.on_data_saver_toggled)
        hbox.append(self.data_saver_switch)

        self.web_view = BlinkGTK.WebView.new()
        self.web_view.set_vexpand(True)
        self.web_view.connect("title-changed", lambda v: self.set_title(v.get_title() or ""))

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.append(hbox)
        vbox.append(self.web_view)
        self.set_child(vbox)

    def on_data_saver_toggled(self, switch, _pspec):
        enabled = switch.get_active()
        self.web_view.set_javascript_enabled(not enabled)
        self.web_view.set_images_enabled(not enabled)
        print(f"Data saver mode: {'on' if enabled else 'off'}", flush=True)
        # The page on screen picks up the change when it is reloaded
        if self.web_view.get_uri():
            self.web_view.reload()


def on_activate(app, url):
    window = DataSaverBrowser(application=app)
    window.present()
    window.web_view.load_uri(url)


def main():
    url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com/"
    ok, _argv = BlinkGTK.gtk_init(sys.argv[:1])
    if not ok:
        print("Could not initialize BlinkGTK", file=sys.stderr)
        return 1
    app = Gtk.Application(application_id="org.example.DataSaver")
    app.connect("activate", on_activate, url)
    rc = BlinkGTK.gtk_application_run(app)
    BlinkGTK.gtk_shutdown()
    return rc


if __name__ == "__main__":
    sys.exit(main())

Turning the switch on disables JavaScript and images and reloads the page.

Example 2: A Profile System

Setting combinations are defined as data classes and switched with a drop-down.

#!/usr/bin/env python3
"""A browser that switches between setting combinations (profiles)"""
import sys
from dataclasses import dataclass

import gi

gi.require_version("Gtk", "4.0")
gi.require_version("BlinkGTK", "0.1")
from gi.repository import BlinkGTK, Gtk  # noqa: E402


@dataclass
class BrowserProfile:
    name: str
    javascript: bool
    images: bool
    storage: bool

    def apply_to(self, web_view: BlinkGTK.WebView) -> None:
        web_view.set_javascript_enabled(self.javascript)
        web_view.set_images_enabled(self.images)
        web_view.set_local_storage_enabled(self.storage)


PROFILES = [
    BrowserProfile("Normal", javascript=True, images=True, storage=True),
    BrowserProfile("Data saver", javascript=False, images=False, storage=True),
    BrowserProfile("Privacy", javascript=False, images=False, storage=False),
]


class ProfileBrowser(Gtk.ApplicationWindow):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.set_title("Profile Browser")
        self.set_default_size(1000, 700)

        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        for side in ("start", "end", "top", "bottom"):
            getattr(hbox, f"set_margin_{side}")(10)
        hbox.append(Gtk.Label(label="Profile:"))
        self.profile_dropdown = Gtk.DropDown.new_from_strings([p.name for p in PROFILES])
        self.profile_dropdown.connect("notify::selected", self.on_profile_changed)
        hbox.append(self.profile_dropdown)

        self.web_view = BlinkGTK.WebView.new()
        self.web_view.set_vexpand(True)
        self.web_view.connect("title-changed", lambda v: self.set_title(v.get_title() or ""))
        PROFILES[0].apply_to(self.web_view)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.append(hbox)
        vbox.append(self.web_view)
        self.set_child(vbox)

    def on_profile_changed(self, dropdown, _pspec):
        profile = PROFILES[dropdown.get_selected()]
        profile.apply_to(self.web_view)
        print(f"Profile: {profile.name}", flush=True)
        if self.web_view.get_uri():
            self.web_view.reload()


def on_activate(app, url):
    window = ProfileBrowser(application=app)
    window.present()
    window.web_view.load_uri(url)


def main():
    url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com/"
    ok, _argv = BlinkGTK.gtk_init(sys.argv[:1])
    if not ok:
        print("Could not initialize BlinkGTK", file=sys.stderr)
        return 1
    app = Gtk.Application(application_id="org.example.Profiles")
    app.connect("activate", on_activate, url)
    rc = BlinkGTK.gtk_application_run(app)
    BlinkGTK.gtk_shutdown()
    return rc


if __name__ == "__main__":
    sys.exit(main())

Example 3: A Browser with Setting Switches

An example that toggles JavaScript, images and local storage with separate switches is the complete browser in the Event Handling Tutorial.


Migrating from WebKitGTK

API Mapping

WebKitGTK sets options through a WebKit.Settings object, while BlinkGTK sets them directly on BlinkGTK.WebView. The method names also differ.

WebKitGTK (Python) BlinkGTK (Python)
settings.set_enable_javascript(enabled) web_view.set_javascript_enabled(enabled)
settings.get_enable_javascript() web_view.get_javascript_enabled()
settings.set_auto_load_images(enabled) web_view.set_images_enabled(enabled)
settings.get_auto_load_images() web_view.get_images_enabled()
settings.set_enable_html5_local_storage(enabled) web_view.set_local_storage_enabled(enabled)
settings.get_enable_html5_local_storage() web_view.get_local_storage_enabled()
settings.set_default_font_size(size) web_view.set_default_font_size(size)
settings.set_user_agent(ua) web_view.set_user_agent(ua)
settings.get_user_agent() web_view.get_user_agent() (None when not set)

Migration Example

Before (WebKitGTK 6.0):

import gi
gi.require_version("WebKit", "6.0")
from gi.repository import WebKit

web_view = WebKit.WebView()
settings = web_view.get_settings()
settings.set_enable_javascript(False)
settings.set_auto_load_images(False)

After (BlinkGTK):

import gi
gi.require_version("BlinkGTK", "0.1")
from gi.repository import BlinkGTK

# Create it after calling BlinkGTK.gtk_init()
web_view = BlinkGTK.WebView.new()
web_view.set_javascript_enabled(False)
web_view.set_images_enabled(False)

Main differences:


Summary

This tutorial showed how to use BlinkGTK settings from Python/PyGObject.

What You Learned

Next Steps


Author: BlinkGTK Development Team
License: BSD 3-Clause
Feedback: daisy19@gmail.com