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 without a localhost HTTP server (tkwry://on macOS/Linux; Windows defaults tohttps://tkwry.localhost) - 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
💡 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.
🌐 Platform notes
Pre-built abi3 wheels: Windows and macOS. Linux is source-only (best-effort by design).
| 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.
🔧 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.
🧩 Features
Embedding & layout
- Native child of your Tk surface (
build_as_child) — not a floating overlay - Bounds / visibility follow
<Configure>,<Map>,<Unmap>(Notebook tabs hide unmapped views) - Works with
pack/grid/place,Notebook, andPanedWindow; window chrome is the host Toplevel (Layout / resize)
Local apps & bridge
app=serves assets without a localhost HTTP server (tkwry://on macOS/Linux; Windows defaults tohttps://tkwry.localhost)- IPC / RPC / emit between JS and Python (docs/rpc.md)
- Origin-scoped bridge by default;
untrusted=for arbitrary sites (docs/trust.md)
Browser-ish APIs
WebSession/ profiles, cookies (Usage — Shared session); navigation hooks, downloads, print, DevTools (platforms)- Native file drag & drop into the WebView area (notify-only)
Host integration
- Typed create / eval / navigation / download failure signals on the Tk thread
- Lifecycle callbacks deferred onto Tk (avoids native-thread deadlocks)
tkwry.testingwait helpers for integration tests
Plotly / Folium / Markdown demos live under Examples. Prefer
tkwry_browser.py as the full-layout sample
(docs/examples-browser.md).
📁 Examples
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
Start here: mini-browser
The easiest way to see tkwry in a full layout: toolbar + side pane + content tabs, all as child WebViews.
| macOS · dark | Windows · light |
|---|---|
| Script | Description |
|---|---|
examples/tkwry_browser.py |
Flagship mini-browser (single file): app= toolbar / side / Settings, separate content WebSession, New Tab start page, profiles, shortcuts |
python examples/tkwry_browser.py
python examples/tkwry_browser.py --private
Architecture, trust split, and what to copy: docs/examples-browser.md.
Focused demos
| Script | Description |
|---|---|
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/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
Related: Jupyter-style widgets (tkipw)
Built on tkwry. Use when you want the usual ipywidgets / anywidget stack in Tk (not plain HTML + JS):
| Script | Description |
|---|---|
plotly_demo.py |
Plotly FigureWidget |
ipyleaflet_demo.py |
Live ipyleaflet map |
See the tkipw examples for more.
⚠️ Known limitations
Short checklist — details live in Platform notes (especially macOS embedding).
Platforms
- Windows — WebView2 Runtime required; missing → create-failed signals (install notes)
- Linux — no PyPI wheel (by design); best-effort source install; prefer sequential
eval_js_with_callbackacross multiple views (Linux)
Engine gaps / partial wraps (no invented shims)
- Print — system dialog (
print(); macOS alsoprint_with_optionsfor margins); no PDF / no result (Print) - Downloads — start-deny only; no mid-flight abort, pause/resume, or progress % (Downloads)
- Screenshot / find in page — not exposed as tkwry APIs (Windows may still show engine Ctrl+F chrome) (Screenshot, Find)
macOS / Windows quirks
- macOS — import
tkwrybefore AppKit; IME not Safari-parity; inlineurl()may beNone; DevTools needsdevtools=Truethenopen_devtools()(private APIs — avoid Mac App Store) (macOS embedding, DevTools) - Windows DevTools —
open_devtools()works;close_devtoolsis a no-op;is_devtools_openalwaysFalse(DevTools)
Trust & session
- Shared non-ephemeral
WebSession+app=must use the same root; do not share a persistent profile with untrusted sites - External content / IPC defaults and
untrusted=— Trust boundaries
Lifecycle & IPC
- Sync
on_navigation/on_new_window/on_download/ create-timepermission_handlermay block the engine until they return (wait capped ~60s); do not create a WebView fromon_new_window(lifecycle callbacks) - RPC cancel /
destroy()are cooperative only; async queues cap at 2048 each; IPC/RPC messages at 10 MiB (RPC limits, timeout/cancel) - Eval / navigation timeouts surface typed events/errors on the Tk thread (not raised on the WebKit thread)
- Native drag & drop is WebView area only and notify-only (cannot deny from Python; use tkinterdnd2 for arbitrary Tk widgets)
See CHANGELOG.md for release history.
📤 Packaging (best-effort)
Freeze a tkwry app to a Windows .exe or macOS .app with PyInstaller or
Nuitka. Not CI-verified in 0.1.x — verify on your target OS. Full notes:
docs/packaging.md.
pip install pyinstaller tkwry # or: pip install nuitka tkwry
PyInstaller — Windows .exe
pyinstaller --noconsole --onefile --collect-submodules tkwry --name MyApp main.py
PyInstaller — macOS .app
pyinstaller --windowed --onedir --collect-submodules tkwry --name MyApp main.py
Nuitka — Windows one-file .exe
python -m nuitka --standalone --onefile --windows-console-mode=disable --enable-plugin=tk-inter --include-package=tkwry --include-distribution-metadata=tkwry --output-filename=MyApp.exe main.py
Nuitka — macOS .app (Homebrew: include --static-libpython=no)
python -m nuitka --standalone --macos-create-app-bundle --static-libpython=no --enable-plugin=tk-inter --include-package=tkwry --include-distribution-metadata=tkwry --macos-app-name=MyApp main.py
Always collect / include the tkwry package (native _core). Windows
users still need WebView2.
Samples for examples/tkwry_browser.py:
docs/examples-browser.md — Packaging.
app= data dirs:
docs/packaging.md.
🗂 Documentation
| Topic | Doc |
|---|---|
Usage (minimal app, app=, hidden hosts, UA, API) |
docs/usage.md |
| Mini-browser example (flagship layout / sessions / trust) | docs/examples-browser.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 |
| wry embedding / API ownership map | docs/wry-embedding.md |
Packaging (PyInstaller / Nuitka → .exe / .app) |
docs/packaging.md |
📝 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.8
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.8.tar.gz | 969.6 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| tkwry-0.1.8-cp310-abi3-win_arm64.whl | CPython 3.10 | abi3 | Windows ARM64 | Details |
| tkwry-0.1.8-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| tkwry-0.1.8-cp310-abi3-macosx_11_0_x86_64.whl | CPython 3.10 | abi3 | macOS 11.0+ x86-64 | Details |
| tkwry-0.1.8-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 3.8 MB
Release files / tkwry-0.1.8.tar.gz
| Download URL | tkwry-0.1.8.tar.gz |
|---|---|
| Size | 969.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7e1d4ade4ab5eb38152554a3c885af12f1c8c746d67e2ebb0741e634f79175b9
|
|
BLAKE2b-256 checksum How to use checksums |
a14d9634c2b3df2f07f60ea2d5549de67a107815a82fedc76e00cdd7d2cc6896
|
| 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 Sep 5, 2026.
Transparency logRelease files / tkwry-0.1.8-cp310-abi3-win_arm64.whl
| Download URL | tkwry-0.1.8-cp310-abi3-win_arm64.whl |
|---|---|
| Size | 599.5 kB |
| Tags | CPython 3.10 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
a12381990423fda9f7d997c3600029ddf48f41ba4694c34cdce98b9f642abed7
|
|
BLAKE2b-256 checksum How to use checksums |
ca37167175f0de81900e1114f2fd94df024d56f166fa70c743b0d74fdf9cb912
|
| 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 Sep 5, 2026.
Transparency logRelease files / tkwry-0.1.8-cp310-abi3-win_amd64.whl
| Download URL | tkwry-0.1.8-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 621.6 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
89d8c90443de15d245ff2dc3ab8400086f4d620a9a2a9fe6f8d9cab1f5b90d39
|
|
BLAKE2b-256 checksum How to use checksums |
2073e46d2cd9f494a15a0d89818d003980b859c852dfc283414a6a4db406a338
|
| 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 Sep 5, 2026.
Transparency logRelease files / tkwry-0.1.8-cp310-abi3-macosx_11_0_x86_64.whl
| Download URL | tkwry-0.1.8-cp310-abi3-macosx_11_0_x86_64.whl |
|---|---|
| Size | 827.1 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
480ab9cd13c26d8f2b2adb59b84486cd1e4f933e8f92fab3bb2f33566c4f29f7
|
|
BLAKE2b-256 checksum How to use checksums |
4add915efb4ccb653af18030e7198c696cdeafa781c1b6ea5f462091fff36dbb
|
| 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 Sep 5, 2026.
Transparency logRelease files / tkwry-0.1.8-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | tkwry-0.1.8-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 793.6 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
42327ce6205a68cd6d07746848f4751d886f29642a89d74a2843a7b08da6a221
|
|
BLAKE2b-256 checksum How to use checksums |
9c4635a353bae3e1420af601e15065363e9660da992567f348855ac739310f84
|
| 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 Sep 5, 2026.
Transparency log