tkwry
Keep Tkinter — give it the WebView it never had.
Embed a real system WebView (wry) inside your Frame: modern HTML, JS, and IPC in the same layout as your buttons and tabs — one mainloop, no floating overlay.
Alpha — Early preview (see PyPI badge for the current version). APIs and behavior may change without notice. Not recommended for production use yet.
📖 Overview
Tkinter is still a solid GUI shell — it just had no first-class way to host modern web content inside a widget. Overlay-style WebViews drift out of sync when you move, resize, or switch tabs.
tkwry fills that missing piece:
- True child embedding —
build_as_childvia HWND, NSView, or X11 window ID - One event loop — Tk
mainlooponly; no separate app runtime - Local apps —
app=serves HTML/CSS/JS viatkwry://(no localhost HTTP server) - IPC / RPC / emit — JS↔Python events, request/response, and streams without freezing the UI
- Trust boundaries — IPC/RPC default to the initial origin;
untrusted=Truefor arbitrary sites - Layout-aware — tracks
pack/grid/place, tabs, andPanedWindow
Pre-built abi3 wheels ship for Windows and macOS. Linux is source-only (best-effort by design) — see Platform notes.
🗂 Documentation
| Topic | Doc |
|---|---|
Usage (minimal app, app=, hidden hosts, UA, API) |
docs/usage.md |
Trust boundaries (untrusted, bridge_origins, recipes) |
docs/trust.md |
IPC / RPC / emit (expose, call / stream, cancel, limits) |
docs/rpc.md |
| Platform notes (Windows / macOS / Linux, print, window chrome) | docs/platforms.md |
| Packaging (PyInstaller / Nuitka notes — not CI-verified in 0.1.x) | docs/packaging.md |
🔧 Requirements
- Python 3.10+
- Tkinter (included with most Python builds)
- Building from source (git clone,
pip install git+…, or Linux) — Rust toolchain (stable);pipuses maturin as the build backend - Windows (x86_64, arm64) — WebView2 Runtime (no fallback engine; see Platform notes)
- macOS — 11 (Big Sur)+, arm64 or x86_64; system WKWebView
- Linux — WebKitGTK 4.1 + GTK 3; X11 or XWayland (
$DISPLAY); source build only (see Installation and Platform notes)
📦 Installation
PyPI (recommended — Windows / macOS wheels)
pip install tkwry
From a git clone (source build)
Cloning the repo and installing locally compiles the Rust extension on your machine. You need a Rust toolchain (rustup) and platform runtimes from Requirements above (WebView2 on Windows, etc.). pip pulls in maturin automatically as the build backend.
git clone https://github.com/mashu3/tkwry.git
cd tkwry
pip install -e .
Use this for development and for running the examples from the tree.
Install a git revision with pip (source build)
pip install git+https://github.com/mashu3/tkwry.git
This builds from source (sdist via git), not a pre-built wheel — needs Rust, same as pip install .. Prefer the PyPI wheel on Windows and macOS unless you need unreleased commits.
Linux (source install)
Install system dependencies, then build from source (support posture: Platform notes):
# Debian / Ubuntu
sudo apt install \
libwebkit2gtk-4.1-dev \
libgtk-3-dev \
libglib2.0-dev
# Runtime (for end users of your app)
# sudo apt install libwebkit2gtk-4.1-0 libgtk-3-0
pip install maturin
git clone https://github.com/mashu3/tkwry.git
cd tkwry
pip install .
GTK events are pumped automatically on a Tk timer while your app runs.
🚀 Usage
Basic WebView
import tkinter as tk
from tkwry import WebView
root = tk.Tk()
root.geometry("900x600")
frame = tk.Frame(root, bg="#222")
frame.pack(fill="both", expand=True, padx=8, pady=8)
web = WebView(frame, url="https://github.com")
web.when_failed(lambda exc: print("native create failed:", exc))
root.mainloop()
The constructor does not raise if native create fails. Handle
when_failed / <<WebViewCreateFailed>>. Minimal app, app=, hidden hosts,
User-Agent, downloads, cleanup, and the API table:
Usage
(Minimal app).
IPC / RPC / stream: docs/rpc.md.
Trust (untrusted, bridge_origins): docs/trust.md.
⚠️ Known limitations
Short checklist — details live in Platform notes (especially macOS embedding).
- Alpha — APIs may change; not for production yet (see banner above)
- Windows — WebView2 Runtime required; missing runtime →
creation_failed/<<WebViewCreateFailed>>(gated APIs raiseWebViewCreationErrorwith install text) - Print —
web.print()opens the system dialog; no PDF, no return value, no success/fail/cancel (wry has none). macOS:print_with_options(…margins…)(still no result); Win/Linux →OSError. See Platform notes — Print - Downloads — cancel is start-deny only (
on_download→False/ allowlist); no mid-flight abort, pause/resume, or progress % until wry exposes them.in_flight_downloadsis observational. See Platform notes — Downloads - Window chrome — title / icon / geometry / fullscreen / min/max /
-topmostare the host Toplevel (configure_window); WebView size follows the Frame (sync_bounds). See Usage — Layout / resize - Windows DevTools — wry/WebView2 reports
is_devtools_open()asFalseandclose_devtools()is a no-op;open_devtools()still opens the inspector - Linux — no PyPI wheel (by design); best-effort source install
- Linux concurrent
eval_js_with_callback— evaluating on multiple WebViews at once can stall WebKitGTK; prefer sequential evals (see Linux) - Shared
WebSession+app=— WebViews that share a non-ephemeral session must use the sameapp=root (ValueErrorotherwise; Linux can registertkwry://only once per context); do not share a persistent profile with untrusted sites - Trust / external content — RPC/IPC default to the initial origin (optional path prefix /
bridge_allow);bridge_origins="*"warns and needsexpose(..., allow_any_origin=True);app=locks navigation totkwry://(navigation_allow/open_external=Truefor extra origins + system browser);untrusted=Truealso denies downloads unlessdownload_allow/on_downloadpermits (see Trust boundaries) - macOS DevTools — create with
devtools=True, thenopen_devtools()(flag alone does not open;open_devtools()without the flag is a no-op on macOS); uses private APIs — avoid in Mac App Store builds - macOS IME / focus — not Safari-parity; mid-composition focus flips can mis-route input
- macOS import order — import
tkwrybefore AppKit/NSApplication, or you may see a double titlebar url()on macOS — may beNonefor inline HTML until a concreteload_url(WKWebView has no documentNSURL)- Sync hooks / queues —
on_navigation/on_new_window/ create-timepermission_handlermay block WebKit up to ~60s; do not create a WebView fromon_new_window(useopen_external=True/open_in_browser); async event queues cap at 2048; IPC/RPC messages cap at 10 MiB (see Usage — Navigation / lifecycle callbacks) - RPC cancel / destroy — timeout, JS
cancel, anddestroy()are cooperative only (rpc_cancelled()), including open streams; Python cannot preempt a running worker.destroy()joins the pool for ~2 seconds; leftover threads are logged to stderr (see IPC / RPC / emit) - Eval / navigation timeout —
eval_js_with_callbacktimeout (30s) isWebViewTimeoutError(on_error,<<WebViewEvalFailed>>,last_eval_error);on_navigation/on_new_windowtimeout still returns the default deny and signalsWebViewNavigationError(<<WebViewNavigationFailed>>,last_navigation_error) — not raised on the WebKit thread - Drag & drop — WebView area only (use tkinterdnd2 for arbitrary Tk widgets)
- Screenshot — no
WebViewcapture API; wry 0.56.1 does not expose one yet (wry#1674). tkwry will wrap it when upstream ships; no JS fallback (see Platform notes)
See CHANGELOG.md for release history.
🌐 Platform notes
Pre-built wheels: Windows and macOS. Linux is source-only (best-effort).
| OS | Arch | Parent handle | Engine |
|---|---|---|---|
| Windows | x86_64, arm64 | Frame.winfo_id() → HWND |
WebView2 |
| macOS | arm64, x86_64 | Toplevel content NSView |
WKWebView |
| Linux | — | winfo_id() → X11 window ID |
WebKitGTK |
DPI, WebView2, macOS embedding / IME / import order, and Linux eval caveats: Platform notes.
💡 Why child-window embedding?
Tkinter apps already have a window and a layout. The web belongs inside a Frame — same mainloop, same tabs and panes — not in a separate top-level webview that floats beside your UI. tkwry wraps wry's build_as_child against the native surface Tk gives your widgets.
🧩 Features
- Local app assets —
app=+tkwry://(SPA fallback,app_devno-store, ETag/HEAD/Range, default CSP, optional COOP/CORP, boundedwatch_app(); open-then-verify symlink/junction confinement) - IPC / RPC / emit — events vs request/response; sync-generator
stream; worker RPC; typed TypeError; protocolversion; JScancel; Python→JSemit; origin/path allowlist (bridge_origins) +bridge_allow+untrusted=viewer mode - WebSession — shared wry
WebContext; Cookie CRUD onWebView(cookies/set_cookie/ …); sharedapp=roots must match;emit_allbroadcast - Testing helpers —
tkwry.testing.wait_until/wait_ready/wait_eval/wait_title - Child-window embedding — WebView is a native child of your Tk window surface, not a floating overlay
- Bounds & visibility sync — follows
<Configure>,<Map>, and<Unmap>(tabs /Notebookhide unmapped views) - Typed failure signals — create:
<<WebViewCreateFailed>>/when_failed; eval:<<WebViewEvalFailed>>/WebViewTimeoutError; nav hook timeout:<<WebViewNavigationFailed>>/WebViewNavigationError(native still returns the default deny); downloads:<<WebViewDownloadComplete>>/<<WebViewDownloadFailed>>/last_download - Deferred callbacks — IPC, RPC, page load, title, eval results, and DnD queue to Tk (avoids macOS deadlocks)
- URL safety — Python
load_urlnormalizes/validates schemes; in-page nav deniesjavascript:/blob:/… (data:underapp=);app=stays ontkwry://; IPC/RPC origin/path allowlist +bridge_allow - DevTools —
devtools=Trueat create, thenopen_devtools()/close_devtools()/is_devtools_open()(macOS: private APIs) - Print —
web.print()opens the system print dialog (no PDF / no result) - Downloads —
on_download/on_download_complete+download_allow;untrusted=Truedenies unless permitted;last_download+<<WebViewDownloadComplete>>/<<WebViewDownloadFailed>>;unique_download_pathfor same-name files (absolute dest only; no overwrite policy) - Native drag & drop — OS-level file drops into the WebView (no tkinterdnd2)
- Navigation hooks — all handlers on the Tk thread;
on_navigation/on_new_windowblock WebKit until they return - Multiple layouts — works with
pack,grid,place,Notebook, andPanedWindow(see examples) - Plotly-ready — load HTML +
eval_js; demo toggles CDN vs localapp= - Folium-ready — embed Leaflet maps from Folium HTML (right-click to pin)
- Markdown-ready — Monaco editor + live preview in a
PanedWindow(seeexamples/markdown_demo.py; CDN required — or vendor underapp=) - CI-tested —
pyteston Windows (x86_64 + arm64), macOS, and Linux (Xvfb + WebKitGTK)
📁 Examples
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
| Script | Description |
|---|---|
examples/browser_demo.py |
URL bar, tabs, shared WebSession, print / downloads / emit_all (bridge_origins="*"; no expose) |
examples/ipc_demo.py |
IPC events, RPC (call / kwargs / worker), stream (ticks + cancel), and emit |
examples/multi_demo.py |
Multiple WebViews, tabs, panes; emit_all flash |
examples/plotly_demo.py |
Plotly charts — CDN or local app= (pip install plotly) |
examples/folium_demo.py |
Folium maps (pip install folium; tiles need the network) |
examples/markdown_demo.py |
Monaco markdown editor + live preview (CDN) |
examples/dnd_demo.py |
Native file drag & drop into WebView |
python examples/browser_demo.py
python examples/ipc_demo.py
python examples/multi_demo.py
python examples/plotly_demo.py
python examples/folium_demo.py
python examples/markdown_demo.py
python examples/dnd_demo.py
📝 License
This project is licensed under the MIT License. See LICENSE.
This project links against wry, which is dual-licensed (Apache-2.0 or MIT). tkwry uses wry under MIT; see NOTICE for attribution.
👨💻 Author
Metadata
Release files for tkwry 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tkwry-0.1.6.tar.gz | 313.2 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| tkwry-0.1.6-cp310-abi3-win_arm64.whl | CPython 3.10 | abi3 | Windows ARM64 | Details |
| tkwry-0.1.6-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| tkwry-0.1.6-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| tkwry-0.1.6-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 3.0 MB
Release files / tkwry-0.1.6.tar.gz
| Download URL | tkwry-0.1.6.tar.gz |
|---|---|
| Size | 313.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
845b7c05d30ffe143fb5068f220a7a7721fe0f02594e7f4374cb11773f9f74df
|
|
BLAKE2b-256 checksum How to use checksums |
2de6219d96cc02cf8da458bf6510345c5b4930ecb70bfbebcea5e7649f00df6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency logRelease files / tkwry-0.1.6-cp310-abi3-win_arm64.whl
| Download URL | tkwry-0.1.6-cp310-abi3-win_arm64.whl |
|---|---|
| Size | 572.8 kB |
| Tags | CPython 3.10 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
0b80843f931b441db2b4e41390c03d532c64ea2ccef521431b142953b4722f19
|
|
BLAKE2b-256 checksum How to use checksums |
6544c46b23ef0704b8aa638bc645818b0fe6f6af71a0ec41f6909acf898d8151
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency logRelease files / tkwry-0.1.6-cp310-abi3-win_amd64.whl
| Download URL | tkwry-0.1.6-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 593.3 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
fd103e7695873fc6d1adbb6eb9e94289e57269ea8bfd26fdea4cf9bc9a1fd0ee
|
|
BLAKE2b-256 checksum How to use checksums |
28c9e6eeef3a5526499e4b7c54a65aef6aaaa7b24bbfaa8f2d0c5ba90abf1f3c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency logRelease files / tkwry-0.1.6-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | tkwry-0.1.6-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 762.5 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
531373a0abdb457ca658e710ea0f134d43a69c6c15ec8824aa86e0aa3e43ab52
|
|
BLAKE2b-256 checksum How to use checksums |
b1b05bd3dd8f7fcda643b530447ac10835e4028a7cb60241b1cbfa1f52dbe23a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency logRelease files / tkwry-0.1.6-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | tkwry-0.1.6-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 796.7 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
703798383999456263c07a098e27bb605b7e748e82c904f328beccb668f0a261
|
|
BLAKE2b-256 checksum How to use checksums |
64c9e75ece11ee5423bf4c30ad7f281600071b9b6c1c0b7cc9901b2109ea8863
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency log