Migrating from WebKitGTK

Author: BlinkGTK Project
Last updated: 2026-07-30

日本語

A guide for moving a WebKitGTK 6.0 (GTK4) application to BlinkGTK. The shortest
migration path comes first, followed by a mechanical replacement checklist, the
API mapping tables, the design differences, and an honest list of what WebKitGTK
has that BlinkGTK does not. Every BlinkGTK API named here is mechanically
verified to exist in the bundled header and shared library.

Get it running first

Migrating a typical WebKitGTK app changes only a handful of lines of code. In
addition there are two BlinkGTK-specific preparations that WebKitGTK does
not have:

  1. Linking must go through pkg-configpkg-config --cflags --libs blinkgtk-0.1.
    Hand-written link lines miss required libraries and the app crashes right
    after startup
  2. Chromium runtime resources must be in place — files such as icudtl.dat
    and locales/ are needed at run time. Use the bundled run-with-resources
    wrapper, or point at them with blink_gtk_set_resources_path()

Both are covered step by step in
Building your application.

Before — WebKitGTK 6.0

#include <webkit/webkit.h>
#include <gtk/gtk.h>

int main(int argc, char *argv[])
{
    gtk_init();

    GtkWidget *window = gtk_window_new();
    gtk_window_set_title(GTK_WINDOW(window), "WebKitGTK Browser");
    gtk_window_set_default_size(GTK_WINDOW(window), 1024, 768);

    WebKitWebView *web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
    gtk_window_set_child(GTK_WINDOW(window), GTK_WIDGET(web_view));

    webkit_web_view_load_uri(web_view, "https://example.com/");
    gtk_window_present(GTK_WINDOW(window));

    GMainLoop *loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(loop);
    return 0;
}

After — BlinkGTK

#include <blink_gtk/blink_gtk.h>
#include <gtk/gtk.h>

int main(int argc, char *argv[])
{
    /* Change 1: initialize the engine before GTK */
    if (!blink_gtk_init(&argc, &argv)) {
        g_printerr("blink_gtk_init() failed\n");
        return 1;
    }
    gtk_init();

    GtkWidget *window = gtk_window_new();
    gtk_window_set_title(GTK_WINDOW(window), "BlinkGTK Browser");
    gtk_window_set_default_size(GTK_WINDOW(window), 1024, 768);

    /* Change 2: create the WebView. It returns GtkWidget*, so no cast is
     * needed to make it a child */
    GtkWidget *web_view = blink_web_view_new();
    gtk_window_set_child(GTK_WINDOW(window), web_view);

    /* Change 3: cast with BLINK_WEB_VIEW() when calling BlinkGTK APIs */
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com/");
    gtk_window_present(GTK_WINDOW(window));

    /* Change 4: use the BlinkGTK main loop */
    int status = blink_gtk_run_main_loop();

    /* Change 5: shut down */
    blink_gtk_shutdown();
    return status;
}

Build command change

# Before
cc app.c -o app $(pkg-config --cflags --libs gtk4 webkitgtk-6.0)

# After
cc app.c -o app $(pkg-config --cflags --libs blinkgtk-0.1)

Mechanical replacements (checklist)

API mapping

Settings (WebKitSettings equivalent)

BlinkGTK has no Settings object. Settings are applied directly to the WebView.

WebKitGTK BlinkGTK Notes
webkit_settings_set_enable_javascript() blink_web_view_set_javascript_enabled() No Settings lookup needed
webkit_settings_set_auto_load_images() blink_web_view_set_images_enabled() Same
webkit_settings_set_enable_html5_local_storage() blink_web_view_set_local_storage_enabled() Same
webkit_settings_set_default_font_size() blink_web_view_set_default_font_size() Same name
webkit_settings_set_default_charset() blink_web_view_set_default_encoding()
webkit_settings_set_user_agent() blink_web_view_set_user_agent() Supported

Each set_* has a matching get_*. Details:
Settings API

WebKitGTK BlinkGTK Notes
webkit_web_view_load_uri() blink_web_view_load_uri()
webkit_web_view_load_html() blink_web_view_load_html()
webkit_web_view_go_back() / go_forward() blink_web_view_go_back() / go_forward() Same names
webkit_web_view_can_go_back() / can_go_forward() blink_web_view_can_go_back() / can_go_forward() Same names
webkit_web_view_reload() blink_web_view_reload() Same name
webkit_web_view_stop_loading() blink_web_view_stop()
webkit_web_view_get_uri() / get_title() blink_web_view_get_uri() / get_title() Returned strings need g_free()
webkit_web_view_get_estimated_load_progress() blink_web_view_get_estimated_load_progress() Same name
webkit_web_view_is_loading() blink_web_view_is_loading() Same name

Details: Navigation API

Signals

WebKitGTK BlinkGTK Notes
load-changed load-changed Same name; the event value is BlinkLoadEvent
load-failed load-failed Same name
notify::title title-changed Dedicated signal
notify::uri uri-changed Same
permission-request permission-request Same name. Default is deny; respond with blink_permission_request_allow() / deny()

Details: Signals API

Talking to the page

WebKitGTK BlinkGTK Notes
webkit_web_view_evaluate_javascript() blink_web_view_execute_javascript()
webkit_user_content_manager_add_script() blink_web_view_inject_user_script() No ContentManager lookup
webkit_user_content_manager_add_style_sheet() blink_web_view_inject_user_stylesheet() Same
Script message handlers (script-message-received) blink_web_view_register_message_handler() Page side: window.blinkgtk.postMessage()
(WebKitGTK sends C → page via JS evaluation) blink_web_view_send_message_to_page() Page side: window.blinkgtk.addMessageHandler()
webkit_web_context_register_uri_scheme() blink_web_view_register_custom_scheme() / register_custom_scheme_full() No WebContext; per WebView

Details: App integration API

Customizing the UI

WebKitGTK BlinkGTK Notes
script-dialog signal blink_web_view_set_javascript_dialog_handler() alert / confirm / prompt
run-file-chooser signal blink_web_view_set_file_chooser_handler() Respond with file_chooser_response()
WebKitDownload (decide-policy etc.) blink_web_view_set_download_handler()
authenticate signal blink_web_view_set_auth_handler() Respond with auth_response()
TLS error policy blink_web_view_set_certificate_error_handler()
enter-fullscreen / leave-fullscreen blink_web_view_set_fullscreen_handler()

Details: UI handlers API

Everything else

WebKitGTK BlinkGTK Notes
webkit_web_view_set_zoom_level() blink_web_view_set_zoom_level() Same name
WebKitFindController blink_web_view_find_in_page() / stop_finding() No controller lookup
WebKitPrintOperation blink_web_view_print_to_pdf() PDF output only (no print dialog)
webkit_web_view_get_snapshot() blink_web_view_capture_screenshot() / _async() Saves PNG
WebKitCookieManager blink_web_view_get_cookies() / set_cookie() / delete_all_cookies() No manager lookup
WebKitWebInspector blink_web_view_open_devtools() Opens Chrome DevTools

To find a function by goal, see How do I…?.

Where the thinking changes

  1. No Settings / Manager / Controller objects — WebKitGTK hands you helper
    objects via webkit_web_view_get_settings() and friends; BlinkGTK puts every
    API directly on the WebView
  2. The type is GtkWidget*blink_web_view_new() returns GtkWidget*.
    Pass it to GTK as is; cast with BLINK_WEB_VIEW() for BlinkGTK APIs
  3. Strict initialization order — call blink_gtk_init() before GTK
    (see the lifecycle figure)
  4. Runtime resources must be deployed — Chromium data files are required at
    run time. WebKitGTK has no such step, so check this first when migrating
  5. A Wayland session is required — BlinkGTK is Wayland-only and does not run
    in X11-only environments (WebKitGTK does, so this is a real difference)
  6. The developer tools are Chrome DevTools — instead of WebInspector you get
    Chrome DevTools, including remote debugging
    (DevTools API)

What WebKitGTK has that BlinkGTK does not (yet)

Being honest here. The following currently have no equivalent:

If any of these block your migration, please tell us at
bug reports & requests or
contact@blinkgtk.org.

Frequently asked questions

Can I use WebKitGTK and BlinkGTK in the same process?

Not recommended. Both carry large runtimes; memory usage grows and unexpected
interference (symbols, main-loop contention) is possible.

How is the performance?

JavaScript runs on V8 and rendering uses Chromium's pipeline. The engine is
designed to consume almost no CPU while a page is idle. On the other hand,
Chromium-based engines tend to use more memory than WebKit. Evaluate against
your own workload (see the
engine comparison).

Does it run on X11?

No. A Wayland session is required.

Where should I start?

Build and run the "After" code above by following
Building your application first, then move on
to replacing calls in your own app.

History

Date Changes
2026-07-30 Complete revision — standardized on WebKitGTK 6.0 (GTK4), corrected the User-Agent API entry to "supported" (the previous edition said "not provided"), extended the mapping tables to current features (page interaction, UI handlers, DevTools), added the missing-features section
2026-01-01 First edition