Last Updated: 2026-10-21
Target Version: BlinkGTK 1.2.5 or later
Level: Beginner to Intermediate
Language: 日本語 | English
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).
BlinkGTK.WebViewThe 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() |
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-girDebian / 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.debThe 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).
#!/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.
#!/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().
BlinkGTK.WebViewreload() to apply it. The font family
(set_font_family()) and the minimum font size
(set_minimum_font_size()) apply to the page on screen right
away, without reloading| 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 |
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'}")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()) # Noneget_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).
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'}")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'}")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"))BlinkGTK.FontGeneric has STANDARD,
SERIF, SANS_SERIF and
MONOSPACEfc-list : family)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())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}")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().
#!/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.
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())An example that toggles JavaScript, images and local storage with separate switches is the complete browser in the Event Handling Tutorial.
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) |
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:
WebView methods directlyBlinkGTK.gtk_init() before creating widgets, and
run with BlinkGTK.gtk_application_run()This tutorial showed how to use BlinkGTK settings from Python/PyGObject.
Author: BlinkGTK Development Team
License: BSD 3-Clause
Feedback: daisy19@gmail.com