# Table of Contents - [pywebview | pywebview](#pywebview-pywebview) - [Introduction | pywebview](#introduction-pywebview) - [Blog | pywebview](#blog-pywebview) - [pywebview](#pywebview) - [Donating | pywebview](#donating-pywebview) - [Installation | pywebview](#installation-pywebview) - [API | pywebview](#api-pywebview) - [Examples | pywebview](#examples-pywebview) - [pywebview (v2.4)](#pywebview-v2-4-) - [pywebview](#pywebview) - [Debugging | pywebview](#debugging-pywebview) - [Javascript–Python bridge | pywebview](#javascript-python-bridge-pywebview) - [Usage | pywebview](#usage-pywebview) - [DOM support | pywebview](#dom-support-pywebview) - [Application architecture | pywebview](#application-architecture-pywebview) - [Freezing | pywebview](#freezing-pywebview) - [Security | pywebview](#security-pywebview) - [FAQ | pywebview](#faq-pywebview) - [Web engine | pywebview](#web-engine-pywebview) - [Development | pywebview](#development-pywebview) - [Donating | pywebview](#donating-pywebview) - [Bug reporting | pywebview](#bug-reporting-pywebview) - [Introducing pywebview 3.0 | pywebview](#introducing-pywebview-3-0-pywebview) - [Documentation | pywebview](#documentation-pywebview) - [5.0 has landed | pywebview](#5-0-has-landed-pywebview) - [Menu | pywebview](#menu-pywebview) - [6.0 is here | pywebview](#6-0-is-here-pywebview) - [Installation | pywebview](#installation-pywebview) - [Blog | pywebview](#blog-pywebview) - [Documentation | pywebview](#documentation-pywebview) - [Bug reporting | pywebview](#bug-reporting-pywebview) - [Development | pywebview](#development-pywebview) - [Introducing pywebview 3.0 | pywebview](#introducing-pywebview-3-0-pywebview) - [5.0 has landed | pywebview](#5-0-has-landed-pywebview) - [Application architecture | pywebview](#application-architecture-pywebview) - [Security | pywebview](#security-pywebview) - [Freezing | pywebview](#freezing-pywebview) - [Debugging | pywebview](#debugging-pywebview) - [Web engine | pywebview](#web-engine-pywebview) - [FAQ | pywebview](#faq-pywebview) - [Javascript–Python bridge | pywebview](#javascript-python-bridge-pywebview) - [DOM support | pywebview](#dom-support-pywebview) - [Usage | pywebview](#usage-pywebview) - [pywebview (v2.4)](#pywebview-v2-4-) - [pywebview](#pywebview) - [Installation | pywebview (v2.4)](#installation-pywebview-v2-4-) - [About | pywebview (v2.4)](#about-pywebview-v2-4-) - [About | pywebview](#about-pywebview) - [Installation | pywebview](#installation-pywebview) - [Multiple Windows | pywebview](#multiple-windows-pywebview) - [Drag Drop | pywebview](#drag-drop-pywebview) - [Screens | pywebview](#screens-pywebview) - [Downloads | pywebview](#downloads-pywebview) - [Dom Manipulation | pywebview](#dom-manipulation-pywebview) - [Open File Dialog | pywebview](#open-file-dialog-pywebview) - [Cookies | pywebview](#cookies-pywebview) - [Dom Events | pywebview](#dom-events-pywebview) - [Save File Dialog | pywebview](#save-file-dialog-pywebview) - [Destroy Window | pywebview](#destroy-window-pywebview) - [Expose | pywebview](#expose-pywebview) - [Get Current Url | pywebview](#get-current-url-pywebview) - [Get Elements | pywebview](#get-elements-pywebview) - [Window State | pywebview](#window-state-pywebview) - [Change Url | pywebview](#change-url-pywebview) - [Run Js | pywebview](#run-js-pywebview) - [Toggle Fullscreen | pywebview](#toggle-fullscreen-pywebview) - [Move Window | pywebview](#move-window-pywebview) - [Window Title Change | pywebview](#window-title-change-pywebview) - [Confirm Close | pywebview](#confirm-close-pywebview) - [Cef | pywebview](#cef-pywebview) - [Events | pywebview](#events-pywebview) - [Confirmation Dialog | pywebview](#confirmation-dialog-pywebview) - [Debug | pywebview](#debug-pywebview) - [Focus | pywebview](#focus-pywebview) - [Frameless | pywebview](#frameless-pywebview) - [Fullscreen | pywebview](#fullscreen-pywebview) - [Http Server | pywebview](#http-server-pywebview) - [Icon | pywebview](#icon-pywebview) - [Load Css | pywebview](#load-css-pywebview) - [Load Html | pywebview](#load-html-pywebview) - [Localhost Ssl | pywebview](#localhost-ssl-pywebview) - [On Top | pywebview](#on-top-pywebview) - [Settings | pywebview](#settings-pywebview) - [Hide Window | pywebview](#hide-window-pywebview) - [Evaluate Js Async | pywebview](#evaluate-js-async-pywebview) - [Links | pywebview](#links-pywebview) - [Py2app Setup | pywebview](#py2app-setup-pywebview) - [Pystray Icon | pywebview](#pystray-icon-pywebview) - [Qt Test | pywebview](#qt-test-pywebview) - [Headers | pywebview](#headers-pywebview) - [Resize | pywebview](#resize-pywebview) - [Simple Browser | pywebview](#simple-browser-pywebview) - [Min Size | pywebview](#min-size-pywebview) - [User Agent | pywebview](#user-agent-pywebview) - [Vibrancy | pywebview](#vibrancy-pywebview) - [Dom Traversal | pywebview](#dom-traversal-pywebview) - [Evaluate Js | pywebview](#evaluate-js-pywebview) - [Drag Region | pywebview](#drag-region-pywebview) - [Loading Animation | pywebview](#loading-animation-pywebview) - [Localization | pywebview](#localization-pywebview) - [Remote Debugging | pywebview](#remote-debugging-pywebview) - [State | pywebview](#state-pywebview) - [Transparent | pywebview](#transparent-pywebview) - [Js Api | pywebview](#js-api-pywebview) - [Multiple Servers | pywebview](#multiple-servers-pywebview) - [Multiprocess | pywebview](#multiprocess-pywebview) - [Menu | pywebview](#menu-pywebview) - [Examples | pywebview (v2.4)](#examples-pywebview-v2-4-) - [Examples | pywebview](#examples-pywebview) - [Changelog | pywebview](#changelog-pywebview) - [Documentation | pywebview](#documentation-pywebview) - [Application architecture | pywebview](#application-architecture-pywebview) - [CSS load | pywebview](#css-load-pywebview) - [Security | pywebview](#security-pywebview) - [Debugging | pywebview](#debugging-pywebview) - [Destroy window | pywebview](#destroy-window-pywebview) - [Virtual environment | pywebview](#virtual-environment-pywebview) - [Web engine | pywebview](#web-engine-pywebview) - [Events | pywebview](#events-pywebview) - [HTML load | pywebview](#html-load-pywebview) - [Javascript evaluation | pywebview](#javascript-evaluation-pywebview) - [Loading animation | pywebview](#loading-animation-pywebview) - [Localization | pywebview](#localization-pywebview) - [Javascript API | pywebview](#javascript-api-pywebview) - [Minimum window size | pywebview](#minimum-window-size-pywebview) - [Link types | pywebview](#link-types-pywebview) - [Minimize / restore window | pywebview](#minimize-restore-window-pywebview) - [Multi-window | pywebview](#multi-window-pywebview) - [Resize window | pywebview](#resize-window-pywebview) - [Open file dialog | pywebview](#open-file-dialog-pywebview) - [Toggle full-screen | pywebview](#toggle-full-screen-pywebview) - [Open URL | pywebview](#open-url-pywebview) - [Donating | pywebview](#donating-pywebview) - [Development | pywebview](#development-pywebview) - [pywebview](#pywebview) - [Save file dialog | pywebview](#save-file-dialog-pywebview) - [Bug reporting | pywebview](#bug-reporting-pywebview) - [Change user agent string | pywebview](#change-user-agent-string-pywebview) - [Window title change | pywebview](#window-title-change-pywebview) - [Screens | pywebview](#screens-pywebview) - [Debugging | pywebview](#debugging-pywebview) - [Freezing | pywebview](#freezing-pywebview) - [Installation | pywebview](#installation-pywebview) - [Usage | pywebview](#usage-pywebview) - [Interdomain communication | pywebview](#interdomain-communication-pywebview) - [Hide / show window | pywebview](#hide-show-window-pywebview) - [Move window | pywebview](#move-window-pywebview) - [Frameless window | pywebview](#frameless-window-pywebview) - [Fullscreen window | pywebview](#fullscreen-window-pywebview) - [Get current URL | pywebview](#get-current-url-pywebview) - [Get DOM elements | pywebview](#get-dom-elements-pywebview) - [Quit confirmation dialog | pywebview](#quit-confirmation-dialog-pywebview) - [CEF support | pywebview](#cef-support-pywebview) - [Change URL | pywebview](#change-url-pywebview) - [API | pywebview](#api-pywebview) - [CEF support | pywebview](#cef-support-pywebview) - [Bug reporting | pywebview](#bug-reporting-pywebview) - [Development | pywebview](#development-pywebview) - [Usage | pywebview](#usage-pywebview) - [Donating | pywebview](#donating-pywebview) - [Documentation | pywebview](#documentation-pywebview) - [Application architecture | pywebview](#application-architecture-pywebview) - [Debugging | pywebview](#debugging-pywebview) - [Interdomain communication | pywebview](#interdomain-communication-pywebview) - [Freezing | pywebview](#freezing-pywebview) - [Security | pywebview](#security-pywebview) - [Virtual environment | pywebview](#virtual-environment-pywebview) - [Web engine | pywebview](#web-engine-pywebview) - [API | pywebview](#api-pywebview) - [Change URL | pywebview](#change-url-pywebview) - [CSS load | pywebview](#css-load-pywebview) - [Quit confirmation dialog | pywebview](#quit-confirmation-dialog-pywebview) - [Debugging | pywebview](#debugging-pywebview) - [Events | pywebview](#events-pywebview) - [Destroy window | pywebview](#destroy-window-pywebview) - [Frameless window | pywebview](#frameless-window-pywebview) - [Fullscreen window | pywebview](#fullscreen-window-pywebview) - [Get DOM elements | pywebview](#get-dom-elements-pywebview) - [Get current URL | pywebview](#get-current-url-pywebview) - [Hide / show window | pywebview](#hide-show-window-pywebview) - [Javascript evaluation | pywebview](#javascript-evaluation-pywebview) - [HTML load | pywebview](#html-load-pywebview) - [Javascript API | pywebview](#javascript-api-pywebview) - [Loading animation | pywebview](#loading-animation-pywebview) - [Localization | pywebview](#localization-pywebview) - [Link types | pywebview](#link-types-pywebview) - [Minimize / restore window | pywebview](#minimize-restore-window-pywebview) - [Multi-window | pywebview](#multi-window-pywebview) - [Minimum window size | pywebview](#minimum-window-size-pywebview) - [Open file dialog | pywebview](#open-file-dialog-pywebview) - [Open URL | pywebview](#open-url-pywebview) - [Move window | pywebview](#move-window-pywebview) - [Save file dialog | pywebview](#save-file-dialog-pywebview) - [Resize window | pywebview](#resize-window-pywebview) - [Screens | pywebview](#screens-pywebview) - [Toggle full-screen | pywebview](#toggle-full-screen-pywebview) - [Change user agent string | pywebview](#change-user-agent-string-pywebview) - [Window title change | pywebview](#window-title-change-pywebview) - [Expose | pywebview](#expose-pywebview) --- # pywebview | pywebview [Skip to main content](https://pywebview.flowrl.com/#main-content) Current Version: 6.2.1 View changelog _pywebview_ is a lightweight BSD-licensed cross-platform wrapper around a webview component. _pywebview_ allows to display HTML content in its own native GUI window. It gives you power of web technologies in your desktop application, hiding the fact that GUI is browser based. _pywebview_ ships with a built-in HTTP server, DOM support in Python and window management functionality. Get started by [installing _pywebview_](https://pywebview.flowrl.com/guide/installation) , explore [documentation](https://pywebview.flowrl.com/guide/) or [examples](https://pywebview.flowrl.com/examples/) . If React is your thing, get started right away with [React boilerplate](https://github.com/r0x0r/pywebview-react-boilerplate) . devices Cross-platform -------------- Compatible with Windows, macOS, Linux, and Android, ensuring a consistent user experience across all major operating systems. sync Two-way Javascript↔Python communication --------------------------------------- Facilitate direct communication between Javascript and Python without the need for HTTP or REST. cloud Built-in HTTP server -------------------- Easily serve static files with the integrated HTTP server, simplifying the process of hosting and accessing your web content. grid\_view Window management ----------------- Control the appearance and behavior of the window, including its size, position, and title. Manage multiple windows with ease. widgets Native components ----------------- Utilize native GUI elements such as menus, message boxes, and file dialogs to provide a seamless user interface. code DOM support ----------- Leverage the Python API to manipulate and traverse DOM nodes without resorting to Javascript. folder Enhanced filesystem support --------------------------- Access the full path of dropped files, create save file and open file dialogs on demand. package Bundler friendly ---------------- Easily integrate with popular bundlers like pyinstaller, nuitka, and py2app, streamlining the packaging and distribution of your applications. [Sponsors](https://pywebview.flowrl.com/#sponsors) --------------------------------------------------- [![](https://github.com/r0x0r/pywebview/raw/master/assets/testmuai.svg)](https://www.testmuai.com/?utm_medium=sponsor&utm_source=pywebview) Become a financial contributor and help us sustain our community. More donation options are outlined on the [Donating](https://pywebview.flowrl.com/contributing/donating) page. ![Github Sponsor](https://pywebview.flowrl.com/github_sponsor_button.png) --- # Introduction | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/#main-content) Introduction ============ 10/19/18Less than 1 minute * * * [Introduction](https://pywebview.flowrl.com/guide/#introduction) ================================================================= _pywebview_ is a lightweight native webview wrapper that allows to display HTML content in its own native GUI window. It gives you power of web technologies in your desktop application, hiding the fact that GUI is browser based. _pywebview_ ships with a built-in HTTP server, DOM support in Python and window management functionality. _pywebview_ is available for Windows, macOS, Linux (GTK or QT) and Android. It uses native GUI for creating a web component window: WinForms on Windows, Cocoa on macOS and QT or GTK on Linux. If you choose to freeze your application, _pywebview_ does not bundle a heavy GUI toolkit or web renderer with it keeping the executable size small. _pywebview_ provides advanced features like window manipulation functionality, event system, built-in HTTP server, native GUI elements like application menu and various dialogs, two way communication between Javascript ↔ Python and DOM support. _pywebview_ is created by [Roman Sirokov](https://github.com/r0x0r/) . [Install](https://pywebview.flowrl.com/guide/#install) ------------------------------------------------------- Generally, you should be able to install _pywebview_ with pip install pywebview On some Linux platforms you may need to install additional libraries. Refer to the [installation](https://pywebview.flowrl.com/guide/installation) page for details. [Hello world](https://pywebview.flowrl.com/guide/#hello-world) --------------------------------------------------------------- import webview webview.create_window('Hello world', 'https://pywebview.flowrl.com/') webview.start() [Develop](https://pywebview.flowrl.com/guide/#develop) ------------------------------------------------------- Read the basic concepts in [Usage](https://pywebview.flowrl.com/guide/usage) , dive into [application architecture](https://pywebview.flowrl.com/guide/architecture) . Explore [API](https://pywebview.flowrl.com/api) and check various [examples](https://pywebview.flowrl.com/examples) [Contribute](https://pywebview.flowrl.com/guide/#contribute) ------------------------------------------------------------- Checkout out [contributing guidelines](https://pywebview.flowrl.com/contributing/) [Support the project](https://pywebview.flowrl.com/guide/#support-the-project) ------------------------------------------------------------------------------- If you find _pywebview_ useful, please support it. [![Github Sponsor](https://pywebview.flowrl.com/github_sponsor_button.png)](https://github.com/sponsors/r0x0r) [![Patreon](https://pywebview.flowrl.com/patreon.png)](https://www.patreon.com/bePatron?u=13226105) [![Open Collective](https://pywebview.flowrl.com/opencollective.png)](https://opencollective.com/pywebview/donate) --- # Blog | pywebview [Skip to main content](https://pywebview.flowrl.com/blog/#main-content) Blog ==== 7/10/19Less than 1 minute * * * [Blog](https://pywebview.flowrl.com/blog/#blog) ================================================ ### [2025-08-08 pywebview 6](https://pywebview.flowrl.com/blog/#_2025-08-08-pywebview-6) Another major installment with _pywebview 6_ featuring new state management, network event handling and window specific menus. [Read more](https://pywebview.flowrl.com/blog/pywebview6) ### [2024-03-08 pywebview 5](https://pywebview.flowrl.com/blog/#_2024-03-08-pywebview-5) _pywebview_ 5 has landed with Android support and DOM. [Read more](https://pywebview.flowrl.com/blog/pywebview5) ### [2019-07-11 Introducing pywebview 3.0](https://pywebview.flowrl.com/blog/#_2019-07-11-introducing-pywebview-3-0) _pywebview_ has reached version 3.0 and has a number of breaking changes. [Read more](https://pywebview.flowrl.com/blog/pywebview3) --- # pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/#main-content) 3/9/17Less than 1 minute * * * Thanks for considering contributing to pywebview. _pywebview_ is a small-time project, which gets updated sporadically whenever time permits. Any help is appreciated and the best way to contribute is submitting a pull request. Bug fixes are always welcome. If you wish to submit a new feature, please create an issue and discuss it beforehand. If you found a bug and want to report it, please test it first in a web-browser that is used by default for your operating system to see if the problem is with your code, rather than pywebview. Do not forget to specify on which platform and pywebview version it occurs. To support pywebview financially, consider sponsoring the project. Pywebview has no corporate backing and financial help is welcomed to keep the project alive. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) For other ways to donate refer to the [donation](https://pywebview.flowrl.com/contributing/donating) page. --- # Donating | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/donating#main-content) Donating ======== 10/19/18Less than 1 minute * * * [Donating](https://pywebview.flowrl.com/contributing/donating#donating) ======================================================================== [Recurrring pledge](https://pywebview.flowrl.com/contributing/donating#recurrring-pledge) ------------------------------------------------------------------------------------------ Recurring pledges come perks, like getting email support or featuring your name or logo in the project repository [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [One-time donations](https://pywebview.flowrl.com/contributing/donating#one-time-donations) -------------------------------------------------------------------------------------------- We accept donations via Paypal [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # Installation | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/installation#main-content) Installation ============ 10/19/18About 1 min * * * [Installation](https://pywebview.flowrl.com/guide/installation#installation) ============================================================================= pip install pywebview This will install _pywebview_ with default dependencies for each platform. On Linux you have to explicitly choose between QT and GTK. pip install pywebview[gtk] or # This will install PyQT6 pip install pywebview[qt] Other QT related options are `pywebview[qt5]`, `pywebview[pyside2]` and `pywebview[pyside6]` Other optional dependencies are `pywebview[android]`, `pywebview[cef]` and `pywebview[ssl]`. CEF is available only for Windows. `ssl` option installs a `cryptography` package, which is needed for using https in local HTTP server. [Dependencies](https://pywebview.flowrl.com/guide/installation#dependencies) ----------------------------------------------------------------------------- ### [Windows](https://pywebview.flowrl.com/guide/installation#windows) [pythonnet](https://github.com/pythonnet/pythonnet) (requires > .NET 4.0) To use with the latest Chromium you need [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . If you plan to distribute your software, check out [distribution guidelines](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) too. To use with CEF you need [cefpython](https://github.com/cztomczak/cefpython/) QT can be used on Windows as well. ### [macOS](https://pywebview.flowrl.com/guide/installation#macos) [pyobjc](https://pythonhosted.org/pyobjc/) `PyObjC` comes preinstalled with the Python bundled in macOS. For a stand-alone Python installation you have to install it separately. You do not need the entire `PyObjC` package, these packages suffice pyobjc-core pyobjc-framework-Cocoa pyobjc-framework-Quartz pyobjc-framework-WebKit pyobjc-framework-security You can also use `QT` on macOS. ### [Linux](https://pywebview.flowrl.com/guide/installation#linux) `pip install pywebview[qt]` should take care of QT dependencies. If it does not work or you would like to use GTK, you may try these recipes. To install QtWebChannel on Debian-based systems (more modern, preferred) sudo apt install python3-pyqt5 python3-pyqt5.qtwebengine python3-pyqt5.qtwebchannel libqt5webkit5-dev To install QtWebKit (legacy, but available for more platforms). sudo apt install python3-pyqt5 python3-pyqt5.qtwebkit python-pyqt5 python-pyqt5.qtwebkit libqt5webkit5-dev [PyGObject](https://pygobject.readthedocs.io/en/latest/) is used with GTK. To install dependencies on Ubuntu, use sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-webkit2-4.1 For other distributions, consult the [PyGObject documentation](https://pygobject.readthedocs.io/en/latest/getting_started.html) Note that WebKit2 version 2.22 or greater is required. Warning Starting from Ubuntu Disco Dingo _pywebview_ can be installed via `apt` on Debian based system as `python3-webview` or `python-pywebview`. Ubuntu's distribution lags a few versions behind. If you wish to stay up-to-date, consider installing via `pip`. ### [Android](https://pywebview.flowrl.com/guide/installation#android) For Android development, refer to Kivy's [packaging instructions for Android](https://kivy.org/doc/stable-1.10.1/guide/packaging-android.html) . --- # API | pywebview [Skip to main content](https://pywebview.flowrl.com/api/#main-content) API === 10/19/18About 14 min * * * [API](https://pywebview.flowrl.com/api/#api) ============================================= [webview.active\_window](https://pywebview.flowrl.com/api/#webview-active-window) ---------------------------------------------------------------------------------- webview.active_window() Get an instance of the currently active window [webview.create\_window](https://pywebview.flowrl.com/api/#webview-create-window) ---------------------------------------------------------------------------------- webview.create_window(title, url=None, html=None, js_api=None, width=800, height=600, x=None, y=None, screen=None, resizable=True, fullscreen=False, min_size=(200, 100), hidden=False, frameless=False, easy_drag=True, shadow=False, focus=True, minimized=False, maximized=False, menu=[], on_top=False, confirm_close=False, background_color='#FFFFFF', transparent=False, text_select=False, zoomable=False, draggable=False, vibrancy=False, server=http.BottleServer, server_args={}, localization=None) Create a new _pywebview_ window and returns its instance. Can be used to create multiple windows (except Android). Window is not shown until the GUI loop is started. If the function is invoked during the GUI loop, the window is displayed immediately. * `title` - Window title * `url` - URL to load. If the URL does not have a protocol prefix, it is resolved as a path relative to the application entry point. Alternatively a WSGI server object can be passed to start a local web server. * `html` - HTML code to load. If both URL and HTML are specified, HTML takes precedence. * `js_api` - Expose a python object to the Javascript domain of the current `pywebview` window. Methods of the `js_api` object can be invoked from Javascript by calling `window.pywebview.api.()` functions. Exposed function return a promise that return once function returns. Only basic Python objects (like int, str, dict, ...) can be returned to Javascript. * `width` - Window width in logical pixels. Default is 800px. * `height` - Window height in logical pixels. Default is 600px. * `x` - Window x coordinate in logical pixels. Default is centered. * `y` - Window y coordinate in logical pixels. Default is centered. * `screen` - Screen to display window on. `screen` is a screen instance returned by `webview.screens`. * `resizable` - Whether window can be resized. Default is True * `fullscreen` - Start in fullscreen mode. Default is False * `min_size` - a (width, height) tuple that specifies a minimum window size in logical pixels. Default is 200x100 * `hidden` - Create a window hidden by default. Default is False * `frameless` - Create a frameless window. Default is False. * `easy_drag` - Easy drag mode for frameless windows. Window can be moved by dragging any point. Default is True. Note that easy\_drag has no effect with normal windows. To control dragging on an element basis, see [drag area](https://pywebview.flowrl.com/api.html#drag-area) for details. * `shadow` - Add window shadow. Default is False. _Windows only_. * `focus` - Create a non-focusable window if False. Default is True. * `minimized` - Display window minimized * `maximized` - Display window maximized * `menu` - A list of `Menu` objects to create a window specific menu. This menu overrides the application menu specified in `webview.start`. Not supported on GTK. * `on_top` - Set window to be always on top of other windows. Default is False. * `confirm_close` - Whether to display a window close confirmation dialog. Default is False * `background_color` - Background color of the window displayed before WebView is loaded. Specified as a hex color. Default is white. * `transparent` - Create a transparent window. Not supported on Windows. Default is False. Note that this setting does not hide or make window chrome transparent. To hide window chrome set `frameless` to True. * `text_select` - Enables document text selection. Default is False. To control text selection on per element basis, use [user-select](https://developer.mozilla.org/en-US/docs/Web/CSS/user-select) CSS property. * `zoomable` - Enable document zooming. Default is False * `draggable` - Enable image and link object dragging. Default is False * `vibrancy` - Enable window vibrancy. Default is False. macOS only. * `server` - A custom WSGI server instance for this window. Defaults to BottleServer. * `server_args` - Dictionary of arguments to pass through to the server instantiation * `localization` - pass a localization dictionary for per window localization. [webview.start](https://pywebview.flowrl.com/api/#webview-start) ----------------------------------------------------------------- webview.start(func=None, args=None, localization={}, gui=None, debug=False, http_server=False, http_port=None, user_agent=None, private_mode=True, storage_path=None, menu=[], server=http.BottleServer, ssl=False, server_args={}, icon=None): Start a GUI loop and display previously created windows. This function must be called from a main thread. * `func` - function to invoke upon starting the GUI loop. * `args` - function arguments. Can be either a single value or a tuple of values. * `localization` - a dictionary with localized strings. Default strings and their keys are defined in localization.py * `gui` - force a specific GUI. Allowed values are `cef`, `qt` or `gtk` depending on a platform. See [Web Engine](https://pywebview.flowrl.com/guide/web_engine) for details. * `debug` - enable debug mode. See [Debugging](https://pywebview.flowrl.com/guide/debugging) for details. * `http_server` - enable built-in HTTP server for absolute local paths. For relative paths HTTP server is started automatically and cannot be disabled. For each window, a separate HTTP server is spawned. This option is ignored for non-local URLs. * `http_port` - specify a port number for the HTTP server. By default port is randomized. * `user_agent` - change user agent string. * `private_mode` - Control whether cookies and other persistant objects are stored between session. By default private mode is on and nothing is stored between sessions. * `storage_path` - An optional location on hard drive where to store persistant objects like cookies and local storage. By default `~/.pywebview` is used on \*nix systems and `%APPDATA%\pywebview` on Windows. * `menu` - Pass a list of Menu objects to create an application menu. See [this example](https://pywebview.flowrl.com/examples/menu) for usage details. * `server` - A custom WSGI server instance. Defaults to BottleServer. * `ssl` - If using the default BottleServer (and for now the GTK backend), will use SSL encryption between the webview and the internal server. You need to have `cryptography` pip dependency installed in order to use `ssl`. It is not installed by default. * `server_args` - Dictionary of arguments to pass through to the server instantiation * `icon` - path to application icon. Generally icon should be specified during bundling, but if you need to set it manually, you can use this parameter. Supported formats are `.ico` on Windows and `.icns` on macOS. On Linux support depends on the desktop environment, but generally `.png` icons are supported. #### [Examples](https://pywebview.flowrl.com/api/#examples) * [Simple window](https://pywebview.flowrl.com/examples/open_url.html) * [Multi-window](https://pywebview.flowrl.com/examples/multiple_windows) [webview.screens](https://pywebview.flowrl.com/api/#webview-screens) --------------------------------------------------------------------- webview.screens Return a list of available displays (as `Screen` objects) with the primary display as the first element of the list. #### [Examples](https://pywebview.flowrl.com/api/#examples-1) * [Simple window](https://pywebview.flowrl.com/examples/screens) [webview.settings](https://pywebview.flowrl.com/api/#webview-settings) ----------------------------------------------------------------------- webview.settings = { 'ALLOW_DOWNLOADS': False, 'ALLOW_FILE_URLS': True, 'DRAG_REGION_SELECTOR': 'pywebview-drag-region', 'DRAG_REGION_DIRECT_TARGET_ONLY': False, 'OPEN_EXTERNAL_LINKS_IN_BROWSER': True, 'OPEN_DEVTOOLS_IN_DEBUG': True, 'IGNORE_SSL_ERRORS': False, 'REMOTE_DEBUGGING_PORT': None, 'SHOW_DEFAULT_MENUS': True } Additional options that override default behaviour of _pywebview_ to address popular feature requests. * `ALLOW_DOWNLOADS` Allow file downloads. Disabled by default. * `ALLOW_FILE_URLS` Enable `file://` urls. Disabled by default. * `DRAG_REGION_SELECTOR` CSS selector for a drag region in easy drag mode. Default selector is `.pywebview-drag-region`. * `DRAG_REGION_DIRECT_TARGET_ONLY` When set to True, only elements that directly match the drag region selector are draggable. When False, child elements of a drag region are also draggable. Default is False. * `IGNORE_SSL_ERRORS` Ignore SSL errors. Disabled by default. * `OPEN_EXTERNAL_LINKS_IN_BROWSER`. Open `target=_blank` link in an external browser. Enabled by default. * `OPEN_DEVTOOLS_IN_DEBUG` Open devtools automatically in debug mode. Enabled by default. * `REMOTE_DEBUGGING_PORT` Enable remote debugging when using `edgechromium` or `qt`. Disabled by default. * `SHOW_DEFAULT_MENUS` Show default menus on Cocoa. Enabled by default. * `WEBVIEW2_RUNTIME_PATH` Path to WebView2 runtime. You can use relative paths, which will be resolved relative to the application entry point with support of path resolution for most bundlers. If not set, the system installed runtime is used if present. #### [Examples](https://pywebview.flowrl.com/api/#examples-2) * [File downloads](https://pywebview.flowrl.com/examples/downloads) [webview.token](https://pywebview.flowrl.com/api/#webview-token) ----------------------------------------------------------------- webview.token A CSRF token property unique to the session. The same token is exposed as `window.pywebview.token`. See [Security](https://pywebview.flowrl.com/guide/security) for usage details. [webview.dom](https://pywebview.flowrl.com/api/#webview-dom) ------------------------------------------------------------- ### [webview.dom.DOMEventHandler](https://pywebview.flowrl.com/api/#webview-dom-domeventhandler) DOMEventHandler(callback, prevent_default=False, stop_propagation=False, stop_immediate_propagation=False, debounce=0) A container for an event handler used to control propagation or default behaviour of the event. If `debounce` is greater than zero, Python event handler is debounced by a specified number of milliseconds. This can be useful for events like `dragover` and `mouseover` that generate a constant stream of events resulting in poor performance. `DOMEventHandler` can be used to get a full path of droppped files in `drop` event on the Python side. The file path information is stored in `event['dataTransfer']['files'][0]['pywebviewFullPath']` property of the event object. See [this example](https://pywebview.flowrl.com/examples/drag_drop) for details. #### [Examples](https://pywebview.flowrl.com/api/#examples-3) element.events.click += DOMEventHandler(on_click, prevent_default=True, stop_propagation=True, stop_immediate_propagation=True) element.events.mouseover += DOMEventHandler(on_click, debounce=500) ### [webview.dom.ManipulationMode](https://pywebview.flowrl.com/api/#webview-dom-manipulationmode) Enum that sets the position of a manipulated DOM element. Possible values are: * `LastChild` - element is inserted as a last child of the target * `FirstChild` - element is inserted as a firt child of the target * `Before` - element is inserted before the target * `After` - element is inserted after the target * `Replace` - element is inserted replacing the target Used by `element.append`, `element.copy`, `element.move` and `window.dom.create_element` functions. [webview.Element](https://pywebview.flowrl.com/api/#webview-element) --------------------------------------------------------------------- ### [element.attributes](https://pywebview.flowrl.com/api/#element-attributes) Get or modify element's attributes. `attributes` is a `PropsDict` dict-like object that implements most of dict functions. To add an attribute, you can simply assign a value to a key in `attributes`. Similarly, to remove an attribute, you can set its value to None. #### [Examples](https://pywebview.flowrl.com/api/#examples-4) element.attributes['id'] = 'container-id' # set element's id element.attributes['data-flag'] = '1337' element.attributes['id'] = None # remove element's id del element.attributes['data-flag'] # remove element's data-flag attribute ### [element.classes](https://pywebview.flowrl.com/api/#element-classes) element.classes Get or set element's classes. `classes` is a `ClassList` list-like object that implements a subset of list functions like `append`, `remove` and `clear`. Additionally it has a `toggle` function for toggling a class. #### [Examples](https://pywebview.flowrl.com/api/#examples-5) element.classes = ['container', 'red', 'dotted'] # overwrite element's classes element.classes.remove('red') # remove red class element.classes.add('blue') # add blue class element.classes.toggle('dotted') ### [element.append](https://pywebview.flowrl.com/api/#element-append) element.append(html, mode=webview.dom.ManipulationMode.LastChild) Insert HTML content to the element as a last child. To control the position of the new element, use the `mode` parameter. See [Manipulation mode](https://pywebview.flowrl.com/api.html#manipulation-mode) for possible values. ### [element.blur](https://pywebview.flowrl.com/api/#element-blur) element.blur() Blur element. ### [element.children](https://pywebview.flowrl.com/api/#element-children) element.children Get element's children elements. Returns a list of `Element` objects. ### [element.copy](https://pywebview.flowrl.com/api/#element-copy) element.copy(target=None, mode=webview.dom.ManipulationMode.LastChild, id=None) Create a new copy of the element. `target` can be either another `Element` or a DOM selector string. If target is omitted, a copy is created in the current element's parent. To control the position of the new element, use the `mode` parameter. See [Manipulation mode](https://pywebview.flowrl.com/api.html#manipulation-mode) for possible values. The id parameter is stripped from the copy. Optionally you can set the id of the copy by specifying the `id` parameter. ### [element.empty](https://pywebview.flowrl.com/api/#element-empty) element.empty() Empty element by removing all its children. ### [element.events](https://pywebview.flowrl.com/api/#element-events) element.events A container object of element's all DOM events, ie `events.click`, `event.keydown`. This container is dynamically populated and its contents depend on the events a node has. To subscribe to a DOM event, use the `+=` syntax, e.g. `element.events.click += callback`. Similarly to remove an event listener use `-=`, eg. `element.events.click -= callback`. Callback can be either a function or an instance of `DOMEventHandler` if you need to control propagation of the event. ### [element.focus](https://pywebview.flowrl.com/api/#element-focus) element.focus() Focus element. ### [element.focused](https://pywebview.flowrl.com/api/#element-focused) element.focused Get whether the element is focused. ### [element.hide](https://pywebview.flowrl.com/api/#element-hide) element.hide() Hide element by setting `display: none`. ### [element.id](https://pywebview.flowrl.com/api/#element-id) element.id Get or set element's id. None if id is not set. ### [element.move](https://pywebview.flowrl.com/api/#element-move) element.move(target, mode=webview.dom.ManipulationMode.LastChild) Move element to the `target` that can be either another `Element` or a DOM selector string. To control the position of the new element, use the `mode` parameter. See [Manipulation mode](https://pywebview.flowrl.com/api.html#manipulation-mode) for possible values. #### [Examples](https://pywebview.flowrl.com/api/#examples-6) [DOM Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) ### [element.next](https://pywebview.flowrl.com/api/#element-next) element.next Get element's next sibling. None if no sibling is present. ### [element.off](https://pywebview.flowrl.com/api/#element-off) element.off(event, callback) Remove an event listener. Identical to `element.event.event_name -= callback`. #### [Examples](https://pywebview.flowrl.com/api/#examples-7) # these two are identical element.off('click', callback_func) element.events.click -= callback_func [DOM Events](https://pywebview.flowrl.com/examples/dom_events) ### [element.on](https://pywebview.flowrl.com/api/#element-on) element.on(event, callback) Add an event listener to a DOM event. Callback can be either a function or an instance of `DOMEventHandler` if you need to control propagation of the event. Identical to `element.event.event_name += callback`. #### [Examples](https://pywebview.flowrl.com/api/#examples-8) # these two are identical element.on('click', callback_func) element.events.click += callback_func [DOM Events](https://pywebview.flowrl.com/examples/dom_events) ### [element.parent](https://pywebview.flowrl.com/api/#element-parent) element.parent Get element's parent `Element` or None if root element is reached. ### [element.previous](https://pywebview.flowrl.com/api/#element-previous) element.previous Get element's previous sibling. None if no sibling is present. ### [element.remove](https://pywebview.flowrl.com/api/#element-remove) element.remove() Remove element from DOM. `Element` object is not destroyed, but marked as removed. Trying to access any properties or invoke any functions of the element will result in a warning. [DOM Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) ### [element.show](https://pywebview.flowrl.com/api/#element-show) element.show() Show hidden element. If element was hidden with `element.hide()`, a previous display value is restored. Otherwise `display: block` is set. [DOM Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) ### [element.style](https://pywebview.flowrl.com/api/#element-style) Get or modify element's styles. `style` is a `PropsDict` dict-like object that implements most of dict functions. To add a style declraration, you can simply assign a value to a key in `attributes`. Similarly, to reset a declaration, you can set its value to None. #### [Examples](https://pywebview.flowrl.com/api/#examples-9) element.style['width'] = '100px' # set element's width to 100px element.style['display'] = 'flex' # set element's display property to flex element.style['width'] = None # reset width to auto del element.attributes['display'] # reset display property to block ### [element.tabindex](https://pywebview.flowrl.com/api/#element-tabindex) element.tabindex Get or set element's tabindex. ### [element.tag](https://pywebview.flowrl.com/api/#element-tag) element.tag Get element's tag name. ### [element.text](https://pywebview.flowrl.com/api/#element-text) element.text Get or set element's text content. ### [element.toggle](https://pywebview.flowrl.com/api/#element-toggle) element.toggle() Toggle element's visibility. ### [element.value](https://pywebview.flowrl.com/api/#element-value) element.value Get or set element's value. Applicable only to input elements that have a value. ### [element.visible](https://pywebview.flowrl.com/api/#element-visible) element.visible Get whether the element is visible. [webview.Menu](https://pywebview.flowrl.com/api/#webview-menu) --------------------------------------------------------------- Used to create an application menu. See [this example](https://pywebview.flowrl.com/examples/menu) for usage details. ### [menu.Menu](https://pywebview.flowrl.com/api/#menu-menu) `Menu(title, items=[])`. Instantiate to create a menu that can be either top level menu or a nested menu. `title` is the title of the menu and `items` is a list of actions, separators or other menus. If title is `"__app__"`, then the menu is treated as an application menu on macOS and ignored on other platforms. ### [menu.MenuAction](https://pywebview.flowrl.com/api/#menu-menuaction) `MenuAction(title, function)` Instantiate to create a menu item. `title` is the name of the item and function is a callback that should be called when menu action is clicked. ### [menu.MenuSeparator](https://pywebview.flowrl.com/api/#menu-menuseparator) `MenuSeparator()` Instantiate to create a menu separator. [webview.Screen](https://pywebview.flowrl.com/api/#webview-screen) ------------------------------------------------------------------- Represents a display found on the systems. A list of `Screen` objects is returned by `webview.screens` property. All coordinate and dimension properties (`x`, `y`, `width`, `height`) are in logical pixels. Use the `physical_*` properties to access physical pixel values. ### [screen.height](https://pywebview.flowrl.com/api/#screen-height) screen.height Get display height in logical pixels. ### [screen.width](https://pywebview.flowrl.com/api/#screen-width) screen.width Get display width in logical pixels. ### [screen.x](https://pywebview.flowrl.com/api/#screen-x) screen.x Get X coordinate of the top-left corner of the display in logical pixels. ### [screen.y](https://pywebview.flowrl.com/api/#screen-y) screen.y Get Y coordinate of the top-left corner of the display in logical pixels. ### [screen.scale](https://pywebview.flowrl.com/api/#screen-scale) screen.scale Get the scale factor (DPI scale) for this display. For example, a value of `2.0` indicates a Retina or HiDPI display with 2x scaling, while `1.0` indicates a standard DPI display. ### [screen.physical\_width](https://pywebview.flowrl.com/api/#screen-physical-width) screen.physical_width Get display width in physical pixels. Equal to `width * scale`. ### [screen.physical\_height](https://pywebview.flowrl.com/api/#screen-physical-height) screen.physical_height Get display height in physical pixels. Equal to `height * scale`. ### [screen.physical\_x](https://pywebview.flowrl.com/api/#screen-physical-x) screen.physical_x Get X coordinate of the top-left corner of the display in physical pixels. Equal to `x * scale`. ### [screen.physical\_y](https://pywebview.flowrl.com/api/#screen-physical-y) screen.physical_y Get Y coordinate of the top-left corner of the display in physical pixels. Equal to `y * scale`. ### [screen.dpi](https://pywebview.flowrl.com/api/#screen-dpi) screen.dpi Get the DPI (dots per inch) for this display. Calculated as `scale * 96`. Standard DPI is 96, so a 2x scaled display would report 192 DPI. [webview.Window](https://pywebview.flowrl.com/api/#webview-window) ------------------------------------------------------------------- Represents a window that hosts webview. `window` object is returned by `create_window` function. ### [window.title](https://pywebview.flowrl.com/api/#window-title) window.title Get or set title of the window. ### [window.on\_top](https://pywebview.flowrl.com/api/#window-on-top) window.on_top Get or set whether the window is always on top. ### [window.x](https://pywebview.flowrl.com/api/#window-x) window.x Get X coordinate of the top-left corner of the window in logical pixels. ### [window.y](https://pywebview.flowrl.com/api/#window-y) window.y Get Y coordinate of the top-left corner of the window in logical pixels. For macOS Y-coordinate is measured from the bottom of the screen, but for consistency with other platforms it is converted to a coordinate system with Y=0 at the top of the screen. ### [window.width](https://pywebview.flowrl.com/api/#window-width) window.width Get width of the window in logical pixels. ### [window.height](https://pywebview.flowrl.com/api/#window-height) window.height Get height of the window in logical pixels. ### [window.clear\_cookies](https://pywebview.flowrl.com/api/#window-clear-cookies) window.clear_cookies() Clear all the cookies including `HttpOnly` ones. #### [Example](https://pywebview.flowrl.com/api/#example) * [Cookies](https://pywebview.flowrl.com/examples/cookies) ### [window.create\_confirmation\_dialog](https://pywebview.flowrl.com/api/#window-create-confirmation-dialog) window.create_confirmation_dialog(title, message) Create a confirmation (Ok / Cancel) dialog. ### [window.create\_file\_dialog](https://pywebview.flowrl.com/api/#window-create-file-dialog) window.create_file_dialog(dialog_type=FileDialog.OPEN, directory='', allow_multiple=False, save_filename='', file_types=()) Create an open file (`webview.FileDialog.OPEN`), open folder (`webview.FileDialog.FOLDER`) or save file (`webview.FileDialog.OPEN.SAVE`) dialog. Return a tuple of selected files, None if cancelled. * `allow_multiple=True` enables multiple selection. * `directory` Initial directory. * `save_filename` Default filename for save file dialog. * `file_types` A tuple of supported file type strings in the open file dialog. A file type string must follow this format `"Description (*.ext1;*.ext2...)"`. If the argument is not specified, then the `"All files (*.*)"` mask is used by default. The 'All files' string can be changed in the localization dictionary. #### [Examples](https://pywebview.flowrl.com/api/#examples-10) * [Open-file dialog](https://pywebview.flowrl.com/examples/open_file_dialog) * [Save-file dialog](https://pywebview.flowrl.com/examples/save_file_dialog) ### [window.destroy](https://pywebview.flowrl.com/api/#window-destroy) window.destroy() Destroy the window. [Example](https://pywebview.flowrl.com/examples/destroy_window) ### [window.evaluate\_js](https://pywebview.flowrl.com/api/#window-evaluate-js) window.evaluate_js(script, callback=None) Execute Javascript code. The last evaluated expression is returned. If callback function is supplied, then promises are resolved and the callback function is called with the result as a parameter. Javascript types are converted to Python types, eg. JS objects to dicts, arrays to lists, undefined to None. DOM nodes are serialized using custom serialization. Functions are omitted and circular references are converted to the `[Circular Reference]` string literal. `webview.error.JavascriptException` is thrown if executed codes raises an error. r-strings is a recommended way to load Javascript. Note that the `evaluate_js` employs `eval`, which will fail if `unsafe-eval` CSP is set. Alternatively you may use `window.run_js(code)` that executes Javascript code as is without returning a result. ### [window.expose](https://pywebview.flowrl.com/api/#window-expose) Expose a Python function or functions to JS API. Functions are exposed as `window.pywebview.api.func_name` [Example](https://pywebview.flowrl.com/examples/expose) ### [window.get\_cookies](https://pywebview.flowrl.com/api/#window-get-cookies) window.get_cookies() Return a list of all the cookies set for the current website (as [SimpleCookie](https://docs.python.org/3/library/http.cookies.html) ). ### [window.get\_current\_url](https://pywebview.flowrl.com/api/#window-get-current-url) window.get_current_url() Return the current URL. None if no url is loaded. [Example](https://pywebview.flowrl.com/examples/get_current_url) ### [window.get\_elements](https://pywebview.flowrl.com/api/#window-get-elements) window.get_elements(selector) _DEPRECATED_. Use `window.dom.get_elements` instead. [Example](https://pywebview.flowrl.com/examples/get_elements) ### [window.hide](https://pywebview.flowrl.com/api/#window-hide) window.hide() Hide the window. [Example](https://pywebview.flowrl.com/examples/show_hide.html) ### [window.load\_css](https://pywebview.flowrl.com/api/#window-load-css) window.load_css(css) Load CSS as a string. [Example](https://pywebview.flowrl.com/examples/css_load.html) ### [window.load\_html](https://pywebview.flowrl.com/api/#window-load-html) window.load_html(content, base_uri=base_uri()) Load HTML code. Base URL for resolving relative URLs is set to the directory the program is launched from. Note that you cannot use hashbang anchors when HTML is loaded this way. [Example](https://pywebview.flowrl.com/examples/html_load.html) ### [window.load\_url](https://pywebview.flowrl.com/api/#window-load-url) window.load_url(url) Load a new URL. [Example](https://pywebview.flowrl.com/examples/change_url) ### [window.maximize](https://pywebview.flowrl.com/api/#window-maximize) window.maximize() Maximize window. [Example](https://pywebview.flowrl.com/examples/window_state) ### [window.minimize](https://pywebview.flowrl.com/api/#window-minimize) window.minimize() Minimize window. [Example](https://pywebview.flowrl.com/examples/window_state) ### [window.move](https://pywebview.flowrl.com/api/#window-move) window.move(x, y) Move window to a new position. `x` and `y` are in logical pixels. [Example](https://pywebview.flowrl.com/examples/move_window) ### [window.native](https://pywebview.flowrl.com/api/#window-native) window.native.Handle.ToInt32() # get application window handle on Windows Get a native window object. This can be useful for applying custom styling to the window. Object type depends on the platform `System.Windows.Form` - Windows `AppKit.NSWindow` - macOS `Gtk.ApplicationWindow` - GTK `QMainWindow` - QT `kivy.uix.widget.Widget` - Android The `native` property is available after the `before_show` event is fired. You can also each platform's WebView object via `window.native.webview`. WebView's types are as follows. `Microsoft.Web.WebView2.WinForms.WebView2` - Windows / EdgeChromium `System.Windows.Forms.WebBrowser` - Windows / MSHTML `WebKit.WKWebView` - macOS `gi.repository.WebKit2.WebView` - GTK `QtWebEngineWidgets.QWebEngineView` / `QtWebKitWidgets.QWebView`\- QT `android.webkit.WebView` - Android ### [window.resize](https://pywebview.flowrl.com/api/#window-resize) window.resize(width, height, fix_point=FixPoint.NORTH | FixPoint.WEST) Resize window. `width` and `height` are in logical pixels. Optional parameter fix\_point specifies in respect to which point the window is resized. The parameter accepts values of the `webview.window.FixPoint` enum (`NORTH`, `SOUTH`, `EAST`, `WEST`) [Example](https://pywebview.flowrl.com/examples/minimize.html) ### [window.restore](https://pywebview.flowrl.com/api/#window-restore) window.restore() Restore minimized window. [Example](https://pywebview.flowrl.com/examples/minimize.html) ### [window.run\_js](https://pywebview.flowrl.com/api/#window-run-js) window.run_js('document.body.style.color = "deepred"') Execute Javascript as is without wrapping it in `eval` and helper code. This function does not return a result. [Example](https://pywebview.flowrl.com/examples/run_js) ### [window.set\_title](https://pywebview.flowrl.com/api/#window-set-title) window.set_title(title) _DEPRECATED_. Use `window.title` instead. Change the title of the window. [Example](https://pywebview.flowrl.com/examples/window_title_change) ### [window.show](https://pywebview.flowrl.com/api/#window-show) window.show() Show the window if it is hidden. Has no effect otherwise [Example](https://pywebview.flowrl.com/examples/show_hide.html) ### [window.toggle\_fullscreen](https://pywebview.flowrl.com/api/#window-toggle-fullscreen) window.toggle_fullscreen() Toggle fullscreen mode on the active monitor. [Example](https://pywebview.flowrl.com/examples/toggle_fullscreen) ### [window.dom.body](https://pywebview.flowrl.com/api/#window-dom-body) window.body Get document's body as an `Element` object ### [window.dom.create\_element](https://pywebview.flowrl.com/api/#window-dom-create-element) window.create_element(html, parent=None, mode=webview.dom.ManipulationMode.LastChild) Insert HTML content and returns the Element of the root object. `parent` can be either another `Element` or a DOM selector string. If parent is omited, created DOM is attached to document's body. To control the position of the new element, use the `mode` parameter. See [Manipulation mode](https://pywebview.flowrl.com/api.html#manipulation-mode) for possible values. ### [window.dom.document](https://pywebview.flowrl.com/api/#window-dom-document) window.document Get `window.document` of the loaded page as an `Element` object ### [window.dom.get\_element](https://pywebview.flowrl.com/api/#window-dom-get-element) window.get_element(selector: str) Get a first `Element` matching the selector. None if not found. ### [window.dom.get\_elements](https://pywebview.flowrl.com/api/#window-dom-get-elements) window.get_elements(selector: str) Get a list of `Element` objects matching the selector. ### [window.dom.window](https://pywebview.flowrl.com/api/#window-dom-window) Get DOM document's window `window` as an `Element` object [Window events](https://pywebview.flowrl.com/api/#window-events) ----------------------------------------------------------------- Window object exposes various lifecycle and window management events. To subscribe to an event, use the `+=` syntax, e.g., `window.events.loaded += func`. Duplicate subscriptions are ignored, and the function is invoked only once for duplicate subscribers. To unsubscribe, use the `-=` syntax, e.g., `window.events.loaded -= func`. To access the window object from the event handler, supply the `window` parameter as the first positional argument of the handler. Most window events are asynchronous, and event handlers are executed in separate threads. The `before_show` and `before_load` events are synchronous and block the main thread until handled. ### [window.events.before\_show](https://pywebview.flowrl.com/api/#window-events-before-show) This event is fired just before pywebview window is shown. This is the earliest event that exposes `window.native` property. This event is blocking. ### [window.events.before\_load](https://pywebview.flowrl.com/api/#window-events-before-load) The event is fired right before _pywebview_ code is injected into the page. The event roughly corresponds to `DOMContentLoaded` DOM event. This event is blocking. ### [window.events.closed](https://pywebview.flowrl.com/api/#window-events-closed) The event is fired just before _pywebview_ window is closed. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.closing](https://pywebview.flowrl.com/api/#window-events-closing) The event is fired when _pywebview_ window is about to be closed. If confirm\_close is set, then this event is fired before the close confirmation is displayed. If event handler returns False, the close operation will be cancelled. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.initialized](https://pywebview.flowrl.com/api/#window-events-initialized) The event is fired right after GUI is chosen and HTTP server is started (if applicable). The first parameter `renderer` has a value of the chosen GUI library / web renderer. If event handler returns False, the window creation will be cancelled and GUI loop will not be started (for windows created before the GUI loop is started). This event is blocking. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.loaded](https://pywebview.flowrl.com/api/#window-events-loaded) The event is fired when DOM is ready. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.maximized](https://pywebview.flowrl.com/api/#window-events-maximized) The event is fired when window is maximized (fullscreen on macOS) ### [window.events.minimized](https://pywebview.flowrl.com/api/#window-events-minimized) The event is fired when window is minimized. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.moved](https://pywebview.flowrl.com/api/#window-events-moved) The event is fired when window is moved. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.request\_sent](https://pywebview.flowrl.com/api/#window-events-request-sent) The event is fired when a HTTP request is sent. The event is emitted for every HTTP request, except on macOS where it is emitted only for the main document. The event handler can accept a single argument - a `Request` object that contains the following properties: * `url` - URL of the request * `method` - HTTP method * `headers` - HTTP request headers as a dictionary. If you mutate mutate headers, modified headers will be used for the request. [Example](https://pywebview.flowrl.com/examples/headers) ### [window.events.response\_received](https://pywebview.flowrl.com/api/#window-events-response-received) The event is fired when a HTTP response is received. The event is emitted for every HTTP response, except on macOS where it is emitted only for the main document. The event handler can accept a single argument - a `Response` object that contains the following properties: * `url` - URL of the response * `status` - HTTP status code * `headers` - HTTP response headers as a dictionary Not supported on QT. [Example](https://pywebview.flowrl.com/examples/headers) ### [window.events.restored](https://pywebview.flowrl.com/api/#window-events-restored) The event is fired when window is restored. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.resized](https://pywebview.flowrl.com/api/#window-events-resized) The event is fired when pywebview window is resized. Event handler can either have no or accept (width, height) arguments. [Example](https://pywebview.flowrl.com/examples/events) ### [window.events.shown](https://pywebview.flowrl.com/api/#window-events-shown) The event is fired when pywebview window is shown. [Example](https://pywebview.flowrl.com/examples/events) ### [window.state](https://pywebview.flowrl.com/api/#window-state) An observable class object that holds the state shared between Python and Javascript. Setting any property of this state will result in `pywebview.state` having updated on the Javascript side and vice versa. Both class (`state.`) and index (`state['property']`) notations are supported. Object mutations are not detected. State is unique to a window and is preserved between page loads. State changes fire events that can be subscribed as `pywebview.state += lambda event_type, key, value: pass`. `event_type` is either `change` or `delete`. `key` is a property name and `value` for its value (`None` for delete events). See also [Javascript state events](https://pywebview.flowrl.com/api/#state-events) [Javascript API](https://pywebview.flowrl.com/api/#javascript-api) ------------------------------------------------------------------- _pywebview_ create a global Javascript object `window.pywebview` that has following properties ### [window.pywebview](https://pywebview.flowrl.com/api/#window-pywebview) A global Javascript object that exposes the following properties: * `api` - A namespace for Python functions exposed via `window.expose` or `js_api` argument. * `platform` - Current renderer in use. * `token` - A CSRF token unique to the session that matches `webview.token` on the Python side. * `state` - A shared state object between Python and Javascript. [DOM events](https://pywebview.flowrl.com/api/#dom-events) ----------------------------------------------------------- ### [pywebviewready](https://pywebview.flowrl.com/api/#pywebviewready) _pywebview_ exposes a `window.pywebviewready` event that is fired after `window.pywebview` object is fully created. [Example](https://pywebview.flowrl.com/examples/js_api) ### [State events](https://pywebview.flowrl.com/api/#state-events) `pywebview.state` is an `EventTarget` object that fires two events `change` and `delete`. To subscribe to an event, use `pywebview.state.addEventListener('change', (e) => {})` or `pywebview.state.addEventListener('delete', (e) => {})`. State change is stored in the `event.detail` object in form of `{ key, value }` [Drag area](https://pywebview.flowrl.com/api/#drag-area) --------------------------------------------------------- With a frameless _pywebview_ window, A window can be moved or dragged by adding a special class called `pywebview-drag-region` to any element.
Now window can be moved by dragging this DIV.
The magic class name can be overriden by re-assigning the `webview.settings['DRAG_REGION_SELECTOR']` property. [Example](https://pywebview.flowrl.com/examples/drag_region) --- # Examples | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/#main-content) Examples ======== 10/19/18Less than 1 minute * * * [Examples](https://pywebview.flowrl.com/examples/#examples) ============================================================ You can find examples demonstrating features of _pywebview_ in the sidebar. Below there are a couple of non-trivial examples that demonstrate an application architecture. [React Boilerplate](https://pywebview.flowrl.com/examples/#react-boilerplate) ------------------------------------------------------------------------------ [React boilerplate with parcel-bundler](https://github.com/r0x0r/pywebview-react-boilerplate) . A complete React-based boilerplate with installation, usage and building taken care of out of the box. [React boilerplate with create-react-app](https://github.com/dzc0d3r/pywebview-react-boilerplate/) . A complete React-based boilerplate with installation, usage and building taken care of out of the box. [Serverless application](https://pywebview.flowrl.com/examples/#serverless-application) ---------------------------------------------------------------------------------------- [Serverless application](https://github.com/r0x0r/pywebview/tree/docs/examples/todos) A simple todo application that uses serverless architecture. Communication between frontend and backend is provided by built-in API. ![Windows](https://pywebview.flowrl.com/screenshots/todos-windows.png) #### Windows ![macOS](https://pywebview.flowrl.com/screenshots/todos-macos.png) #### macOS ![Linux](https://pywebview.flowrl.com/screenshots/todos-linux.png) #### Linux [HTTP server application](https://pywebview.flowrl.com/examples/#http-server-application) ------------------------------------------------------------------------------------------ [Flask-based application](https://github.com/r0x0r/pywebview/tree/docs/examples/flask_app) In this example communication between frontend and backend is facilitated by a Flask server. --- # pywebview (v2.4) ![hero](https://pywebview.flowrl.com/logo.png) pywebview (v2.4) ================ Build GUI for your Python program with JavaScript, HTML, and CSS [Get Started →](https://pywebview.flowrl.com/2.4/guide/) WARNING This is documentation for version 2.4. To see the documentation for the current version, proceed [here](https://pywebview.flowrl.com/) [#](https://pywebview.flowrl.com/2.4#getting-started) Getting Started ====================================================================== ### [#](https://pywebview.flowrl.com/2.4#install) Install: pip install pywebview _On Linux you need additional libraries. Refer to the [installation](https://pywebview.flowrl.com/2.4/guide/installation.html) page for details._ ### [#](https://pywebview.flowrl.com/2.4#hello-world) Hello world: import webview webview.create_window('Hello world', 'https://pywebview.flowrl.com/') [#](https://pywebview.flowrl.com/2.4#support-the-project) Support the project ============================================================================== If you find _pywebview_ useful, please support it. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) --- # pywebview Current version: **3.7** [What's new](https://pywebview.flowrl.com/changelog) [#](https://pywebview.flowrl.com/3.7#getting-started) Getting Started ====================================================================== ### [#](https://pywebview.flowrl.com/3.7#install) Install: pip install pywebview _On Linux you need additional libraries. Refer to the [installation](https://pywebview.flowrl.com/3.7/guide/installation.html) page for details._ ### [#](https://pywebview.flowrl.com/3.7#hello-world) Hello world: import webview webview.create_window('Hello world', 'https://pywebview.flowrl.com/') webview.start() Explore [documentation](https://pywebview.flowrl.com/guide) or [examples](https://pywebview.flowrl.com/examples) . If React is your thing, get started right away with [React boilerplate (opens new window)](https://github.com/r0x0r/pywebview-react-boilerplate) . [#](https://pywebview.flowrl.com/3.7#support-the-project) Support the project ============================================================================== If you find _pywebview_ useful, please support it. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) --- # Debugging | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/debugging#main-content) Debugging ========= 10/19/18Less than 1 minute * * * [Debugging](https://pywebview.flowrl.com/guide/debugging#debugging) ==================================================================== To debug Javascript, set `webview.start(debug=True)`. import webview webview.create_window('Woah dude!', 'https://pywebview.flowrl.com/hello') webview.start(debug=True) This will enable web inspector on macOS, GTK and QT (QTWebEngine only). To open the web inspector on macOS, right click on the page and select Inspect. To disable auto-opening of DevTools, set `webview.settings['OPEN_DEVTOOLS_IN_DEBUG'] = False` before invoking `webview.start()`. Debugging Python code on Android is not possible apart from printing message to `logcat`. Use `adb -s logcat | grep python` for displaying log messages related to Python. Frontend code can be debugged with WebView remote debugging. Refer to [this guide](https://developer.chrome.com/docs/devtools/remote-debugging/webviews/) for details. Remote debugging is supported with the `edgechromium` and `qt` renderers. To take remote debugging into use set `webview.settings['REMOTE_DEBUGGING_PORT']` to the port number you wish to run a debugger on. There is no way to attach an external debugger to MSHTML. The `debug` flag enables Javascript error reporting and right-click context menu. To turn on debug logging for `pywebiew` itself, set `PYWEBVIEW_LOG=debug` environment variable before starting the application. --- # Javascript–Python bridge | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/interdomain#main-content) Javascript–Python bridge ======================== 11/28/19About 2 min * * * [Javascript–Python bridge](https://pywebview.flowrl.com/guide/interdomain#javascript%E2%80%93python-bridge) ============================================================================================================ _pywebview_ offers two-way communication between Javascript and Python, enabling interaction between the two languages without a HTTP server. [Shared state](https://pywebview.flowrl.com/guide/interdomain#shared-state) ---------------------------------------------------------------------------- `NEW 6.0` Data can be shared via the `Window.state` (Python) and `pywebview.state` (Javascript) objects. Modifying any property on either state object will result in the state being updated on the other side and vice versa. For example, setting `window.state.hello = 'world'` in Python will automatically propagate to `pywebview.state.hello` in Javascript. Only changes on the top level are propagated, ie if you mutate an object, it won't be updated on the other side. State is specific to its window and is preserved between page (re)loads. Binary data can be passed by converting it to Base64 or such. State changes trigger events that can be subscribed to using `pywebview.state += lambda event_type, key, value: pass`. The `event_type` is either `change` or `delete`. The `key` is the property name, and the `value` is the property's value (`None` for delete events). [Run Javascript from Python](https://pywebview.flowrl.com/guide/interdomain#run-javascript-from-python) -------------------------------------------------------------------------------------------------------- `window.evaluate_js(code, callback=None)` allows you to execute arbitrary Javascript code with a last value returned synchronously. If callback function is supplied, then promises are resolved and the callback function is called with the result as a parameter. Javascript types are converted to Python types, eg. JS objects to dicts, arrays to lists, undefined to None. If executed Javascript code results in an error, the error is rethrown as a `webview.util.JavascriptException` in Python. `evaluate_js` wraps Javascript code in a helper wrapper and executes it using `eval`. [See example](https://pywebview.flowrl.com/examples/evaluate_js) `Window.run_js(code)` executes Javascript code as is without any wrapper code. `run_js` does not return a result or handle exceptions. This can be useful in scenarios, where you need to execute Javascript code with the `unsafe-eval` CSP policy set. [Run Python from Javascript](https://pywebview.flowrl.com/guide/interdomain#run-python-from-javascript) -------------------------------------------------------------------------------------------------------- Executing Python functions from Javascript can be done with two different mechanisms. * by exposing an instance of a Python class to the `js_api` parameter of `create_window`. All the callable methods of the class will be exposed to the JS domain as `pywebview.api.method_name` with correct parameter signatures. Method name must not start with an underscore. Nested classes are allowed and are converted into a nested objects in Javascript. Class attributes starting with an underscore are not exposed. Also nested classes that have `_serializable = False` class attribute are ommited. See an [example](https://pywebview.flowrl.com/examples/js_api) . * by passing your function(s) to window object's `expose(func)`. This will expose a function or functions to the JS domain as `pywebview.api.func_name`. Unlike JS API, `expose` allows to expose functions also at the runtime. If there is a name clash between JS API and exposed functions, the latter takes precedence. See an [example](https://pywebview.flowrl.com/examples/expose) . Exposed function returns a promise that is resolved to its result value. Exceptions are rejected and encapsulated inside a Javascript `Error` object. Stacktrace is available via `error.stack`. Exposed functions are executed in separate threads and are not thread-safe. `pywebview.api` is not guaranteed to be available on the `window.onload` event. Subscribe to the `window.pywebviewready` event instead to make sure that `pywebview.api` is ready. [See example](https://pywebview.flowrl.com/examples/js_api) . --- # Usage | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/usage#main-content) Usage ===== 10/19/18About 3 min * * * [Usage](https://pywebview.flowrl.com/guide/usage#usage) ======================================================== [Basics](https://pywebview.flowrl.com/guide/usage#basics) ---------------------------------------------------------- The bare minimum to get _pywebview_ up and running is import webview window = webview.create_window('Woah dude!', 'https://pywebview.flowrl.com') webview.start() The `create_window` function creates a new window and returns a `Window` object instance. Windows created before `webview.start()` are shown as soon as the GUI loop is started. Windows created after the GUI loop is started are shown immediately. You may create as many windows as you wish. All the opened windows are stored as a list in `webview.windows`. The windows are stored in a creation order. To get an instance of currently active (focused) window use `webview.active_window()` import webview def handler(): print(f'There are {len(webview.windows)} windows') print(f'Active window: {webview.active_window().title}') first_window = webview.create_window('pywebview docs', 'https://pywebview.flowrl.com') second_window = webview.create_window('Woah dude!', 'https://woot.fi') second_window.events.shown += handler webview.start() _pywebview_ gives a choice of using several web renderers. To change a web renderer, set the `gui` parameter of the `start` function to the desired value (e.g `cef` or `qt`). See [Web Engine](https://pywebview.flowrl.com/guide/web_engine) for details. [Backend logic](https://pywebview.flowrl.com/guide/usage#backend-logic) ------------------------------------------------------------------------ `webview.start` starts a GUI loop and blocks further code from execution until the last window is destroyed. Since the GUI loop is blocking, you must execute your backend logic in a separate thread or process. You can execute your backend code by passing your function to `webview.start(func, *args)`. This will launch a separate thread and is identical to starting a thread manually. import webview def custom_logic(window): window.toggle_fullscreen() window.evaluate_js('alert("Nice one brother")') window = webview.create_window('Woah dude!', html='

Woah dude!

') webview.start(custom_logic, window) # anything below this line will be executed after program is finished executing pass [Window object](https://pywebview.flowrl.com/guide/usage#window-object) ------------------------------------------------------------------------ The `Window` object provides a number of functions and properties to interact with the window. Here are some of the commonly used methods. * `window.load_url(url)`: Loads a new URL in the window. * `window.load_html(content)`: Loads HTML content directly into the window. * `window.evaluate_js(script)`: Executes JavaScript code in the window and returns the result. * `window.toggle_fullscreen()`: Toggles the window between fullscreen and windowed mode. * `window.resize(width, height)`: Resizes the window to the specified width and height. * `window.move(x, y)`: Moves the window to the specified x and y coordinates. * `window.hide()`: Hides the window. * `window.show()`: Shows the window if it is hidden. * `window.minimize()`: Minimizes the window. * `window.restore()`: Restores the window if it is minimized or maximized. * `window.destroy()`: Closes the window. For a complete list of functions, refer to [API](https://pywebview.flowrl.com/api) [Window events](https://pywebview.flowrl.com/guide/usage#window-events) ------------------------------------------------------------------------ Window object has these window manipulation and navigation events: `closed`, `closing`, `loaded`, `before_load`, `before_show`, `shown`, `minimized`, `maximized`, `restored`, `resized`, `moved`. Window events can be found under the `window.events` container. To subscribe to an event use the `+=` operator and `-=` for unsubscribing. For example: import webview def on_closing(): print("Window is about to close") window = webview.create_window('Woah dude!', 'https://pywebview.flowrl.com') window.events.closing += on_closing webview.start() [Communication between Javascript and Python](https://pywebview.flowrl.com/guide/usage#communication-between-javascript-and-python) ------------------------------------------------------------------------------------------------------------------------------------ You can both run Javascript code from Python and Python code from Javascript. To run Javascript from Python, use `window.evaluate_js(code)`. The function returns result of the last line in the Javascript code. If code returns a promise, you can resolve it by passing a callback function `window.evaluate_js(code, callback)`. If Javascript throws an error, `window.evaluate_js` raises a `webview.errors.JavascriptException`. Alternatively you may use `window.run_js(code)` that executes Javascript code as is. `run_js` does not return a result. To run Python from Javascript, you need to expose your API class with `webview.create_window(url, js_api=api_instance)`. Class member functions will be available in Javascript domain as `window.pywebview.api.funcName`. You can expose single functions with `window.expose(func)` also during the runtime. See [interdomain communication](https://pywebview.flowrl.com/guide/interdomain) for details. import webview class Api(): def log(self, value): print(value) webview.create_window("Test", html="", js_api=Api()) webview.start() Alternatively you may use a more traditional approach with REST API paired with a WSGI server for interdomain communication. See [Flask app](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) for an example. [HTTP server](https://pywebview.flowrl.com/guide/usage#http-server) -------------------------------------------------------------------- _pywebview_ uses internally [bottle.py](https://bottlepy.org/) HTTP server for serving static files. HTTP server is launched automatically for relative local paths. The entrypoint directory serves as a HTTP server root with everything under the directory and its directories shared. You may want to enable SSL for the server by setting `webview.start(ssl=True)`. import webview webview.create_window('Woah dude!', 'src/index.html') webview.start(ssl=True) If you wish to use an external WSGI compatible HTTP server, you can pass a server application object as an URL. from flask import Flask import webview server = Flask(__name__, static_folder='./assets', template_folder='./templates') @server.route("/") def hello_world(): return "Hello, World!" if __name__ == '__main__': webview.create_window('Flask example', server) webview.start() If your intent is to serve files without an HTTP server using the `file://` protocol, you can achieve this by either using an absolute file path or by prefixing the path with the `file://` protocol. This approach is not recommended as it makes the program harder to distribute and has limitations on how it is handled by a web renderer. import webview # this will be served as file:///home/pywebview/project/index.html webview.create_window('Woah dude!', '/home/pywebview/project/index.html') webview.start() ### [DOM support](https://pywebview.flowrl.com/guide/usage#dom-support) _pywebview_ has got support for basic DOM manipulation, traversal operations and DOM events. See these examples for details [DOM Events](https://pywebview.flowrl.com/examples/dom_events) , [DOM Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) and [DOM Traversal](https://pywebview.flowrl.com/examples/dom_traversal) . --- # DOM support | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/dom#main-content) DOM support =========== 10/31/23About 2 min * * * [DOM support](https://pywebview.flowrl.com/guide/dom#dom-support) ================================================================== Starting from 5.0 _pywebview_ has got support for basic DOM manipulation, traversal operations and DOM events. See these examples for details [DOM Events](https://pywebview.flowrl.com/examples/dom_events) , [DOM Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) and [DOM Traversal](https://pywebview.flowrl.com/examples/dom_traversal) . [Create element](https://pywebview.flowrl.com/guide/dom#create-element) ------------------------------------------------------------------------ element = window.dom.create_element('
new element
') # insert a new element as body's last child element = window.dom.create_element('

Warning

' parent='#container', mode=ManipulationMode.FirstChild) # insert a new element to #containaer as a first child Manipulation Mode can be one of following `LastChild`, `FirstChild`, `Before`, `After` or `Replace`. `LastChild` is a default value. [Get elements](https://pywebview.flowrl.com/guide/dom#get-elements) -------------------------------------------------------------------- element = window.dom.get_element('#element-id') # returns a first matching Element or None elements = window.dom.get_elements('div') # returns a list of matching Elements [Basic information about element](https://pywebview.flowrl.com/guide/dom#basic-information-about-element) ---------------------------------------------------------------------------------------------------------- element.id # return element's id element.classes # return a list like object of element's classes element.style # return a dict like object of element's styles element.tabindex # return element's tab index element.tag # return element's tag name element.text # return element's text content element.value # return input element's value Some element's properties can be set or modified element.id = 'new-id' element.classes.add('green-text') # add .green-text class element.classes.remove('red-background') # remove .red-background class element.classes.toggle('blue-border') # toggle .blue-border class element.style['width'] = '200px' element.tabindex = 108 element.text = 'New content' element.value = 'Luna' [Manupulate element](https://pywebview.flowrl.com/guide/dom#manupulate-element) -------------------------------------------------------------------------------- new_container = window.get_element('#new-container') new_element = element.copy() # copies element as the parent's last child yet_another_element = new_element.copy(new_container, webview.dom.ManipulationMode.FirstChild, "new-id") # copies element to #new-container as a first child yet_another_element = yet_another_element.move('#new-container2') # moves element to #new-container2 as a last child yet_another_element.remove() # remove element new_container.empty() # empty #new-container from its children new_container.append('kick-ass content') # append new DOM to #new-container [Traversal](https://pywebview.flowrl.com/guide/dom#traversal) -------------------------------------------------------------- element.children # return a list of element's children element.next # return a next element in the DOM hierarchy or None element.parent # return element's parent element.previous # return a previous element in the DOM hierarchy or None `body`, `document` and `window` objects can be directly accessed via window.dom.body window.dom.document window.dom.window ### [Element visibility and focus](https://pywebview.flowrl.com/guide/dom#element-visibility-and-focus) element.hide() # hide element print(element.visible) # False element.show() # show element print(element.visible) # True element.toggle() # toggle visibility element.focus() # focus element print(element.focused) # True if element can be focused element.blur() # blur element print(element.focused) # False [Events](https://pywebview.flowrl.com/guide/dom#events) -------------------------------------------------------- DOM events can be subscribed directly from Python def print_handler(e): print(e) def shout_handler(e): print('!!!!!!!!') print(e) print('!!!!!!!!') element.on('click', print_handler) element.events.click += shout_handler # these two ways to subscribe to an event are equivalent element.off('click', print_handler) element.events.click -= shout_handler # as well as these two If you need more control over how DOM events are handled, you can use `webview.dom.DOMEventHandler`. It allows setting `preventDefault`, `stopPropagation`, `stopImmediatePropagation` values, as well as debouncing event handlers. window.dom.document.events.dragover += DOMEventHandler(on_drag, prevent_default=True, stop_propagation=True, stop_immediate_propagation=True, debounce=500) _pywebview_ enhances the `drop` event to support full file path information. window.dom.document.events.drop += lambda e: print(e['domTransfer']['files'][0]) # print a full path of the dropped file --- # Application architecture | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/architecture#main-content) Application architecture ======================== 7/7/19Less than 1 minute * * * [Application architecture](https://pywebview.flowrl.com/guide/architecture#application-architecture) ===================================================================================================== There are several way to build your application using _pywebview_: [Pure web server](https://pywebview.flowrl.com/guide/architecture#pure-web-server) ----------------------------------------------------------------------------------- * The most simple case is pointing to a url. This requires a running web server either remotely or locally webview.create_window('Simple browser', 'https://pywebview.flowrl.com') webview.start() If you point to a local web server, you can start an external HTTP server in a background thread manually and or giving a WSGIRef server instance to the url parameter. server = Flask(__name__, static_folder='.', template_folder='.') webview.create_window('My first pywebview application', server) webview.start() See a complete example [Flask-based application](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) When using a local web server, you should protect your API calls against CSRF attacks. See [security](https://pywebview.flowrl.com/guide/security) for more information. While the `file://` protocol is possible, its use is discouraged as it comes with a number of inherit limitations and is not well supported. [JS API with internal HTTP server](https://pywebview.flowrl.com/guide/architecture#js-api-with-internal-http-server) --------------------------------------------------------------------------------------------------------------------- Another approach is using JS API bridge and serving static content with a built-in HTTP server. JS API bridge allows communication between Python and Javascript domains without a web server. The bridge can be created either with `create_window(..., js_api=Api())` or `window.expose` function. To serve static contents, set entrypoint url to a local relative path. This will start a built-in HTTP server automatically. For more details on communication between Python and Javascript refer to [interdomain communication](https://pywebview.flowrl.com/guide/interdomain) . See an example [serverless application](https://github.com/r0x0r/pywebview/tree/master/examples/todos) for a complete implementation. [Serverless](https://pywebview.flowrl.com/guide/architecture#serverless) ------------------------------------------------------------------------- By loading HTML using `webview.create_window(...html='')` or `window.load_html` you can avoid using a web server altogether. This approach has limitations however, as the file system does not exist in the context of the loaded page. Images and other assets can be loaded only inline using Base64. --- # Freezing | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/freezing#main-content) Freezing ======== 10/19/18About 1 min * * * [Freezing](https://pywebview.flowrl.com/guide/freezing#freezing) ================================================================= [Android](https://pywebview.flowrl.com/guide/freezing#android) --------------------------------------------------------------- pywebview is designed to be built with [buildozer](https://buildozer.readthedocs.io/en/latest/) . You need to include following lines in your `buildozer.spec` to bundle pywebview correctly requirements = python3,kivy,pywebview android.add_jars = `pywebview-android.jar` is shipped with `pywebview` and can be found under `site-packages/pywebview/lib`. To get its full path type from webview import util print(util.android_jar_path()) You can see a sample `bulldozer.spec` [here](https://github.com/r0x0r/pywebview/blob/a2b8d0449b206db75f9f364639b85db6eac7f07e/examples/todos/buildozer.spec) [macOS](https://pywebview.flowrl.com/guide/freezing#macos) ----------------------------------------------------------- Use [py2app](https://py2app.readthedocs.io/en/latest/) . For a reference setup.py for py2app, look [here](https://github.com/r0x0r/pywebview/blob/master/examples/py2app_setup.py) . [Windows / Linux](https://pywebview.flowrl.com/guide/freezing#windows-linux) ----------------------------------------------------------------------------- Use [pyinstaller](https://www.pyinstaller.org/) . Pyinstaller picks all the dependencies found in `pywebview`, even if you don't use them. So for example if you have `PyQt` installed, but use `EdgeChromium` renderer on Windows, pyinstaller will bundle `PyQT` all the same. To prevent that you might want to add unwanted dependencies to `excludes` in your spec file. Basic pyinstaller script to package an application which uses index.html as content pyinstaller main.py --add-data index.html:. For one file build pyinstaller main.py --add-data index.html:. --onefile > \[!warning\] In Linux if you get a `cannot find python3.xx.so error` you must add it to the pyinstaller binary list for the application to work (replace 'x' with python version) > > pyinstaller main.py --add-data index.html:. --add-binary /usr/lib/x86_64-linux-gnu/libpython3.x.so:. --onefile In case of using a Javascript library like vue or react you can build the project and use the build directory to the pyinstaller `--add-data`. > \[!warning\] While using _vite_ change the build directory to something else to not conflict with pyinstller's build directory which is also `./dist` Here is a script to build a vue/react app with pyinstaller (assuming output is your new build directory) pyinstaller main.py --add-data output:. Onefile pyinstaller main.py --add-data output:. --onefile [nuitka](http://nuitka.net/) can be used for freezing as well. You may want to use `--nofollow-import-to` to exclude unwanted dependencies. --- # Security | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/security#main-content) Security ======== 10/19/18Less than 1 minute * * * [Security](https://pywebview.flowrl.com/guide/security#security) ================================================================= It is advisable to enable SSL for local HTTP server. To accomplish this, simply start the application with the `ssl` paramater set to True `webview.start(ssl=True)`. You need to have `cryptography` pip dependency installed in order to use `ssl`. It is not installed by default. If you employ a REST API, [CSRF attacks](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) can be a major concern. _pywebview_ mitigates this risk by generating a session-unique token that is accessible in Python as `webview.token` and in JavaScript as `window.pywebview.token`. For more information on securing APIs, refer to the [CSRF Prevention Cheat Sheet](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet) . You can also see a practical example in the [Flask app](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) . --- # FAQ | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/faq#main-content) FAQ === 10/31/23About 1 min * * * [FAQ](https://pywebview.flowrl.com/guide/faq#faq) ================================================== [How do I set an application icon?](https://pywebview.flowrl.com/guide/faq#how-do-i-set-an-application-icon) ------------------------------------------------------------------------------------------------------------- For macOS, Windows, and Android, the application icon is set via a bundler and embedded in the resulting executable. For GTK and QT, you can set the application icon using `webview.start(icon=icon_path)`, but you might need some additional adjustments to get your icon visible depending on the window manager you use. [Why does _pywebview_ have to run on a main thread?](https://pywebview.flowrl.com/guide/faq#why-does-pywebview-have-to-run-on-a-main-thread) --------------------------------------------------------------------------------------------------------------------------------------------- This is dictated by underlying GUI libraries _pywebview_ is based on. GUI loop is expected to run on a main thread. While some libraries allow the GUI to be run in a sub-thread, Cocoa has a strict requirement regarding the main thread. If you need your logic to run in a main thread, use the `multiprocessing` module. [webview has no attribute create\_window](https://pywebview.flowrl.com/guide/faq#webview-has-no-attribute-create-window) ------------------------------------------------------------------------------------------------------------------------- You probably have a file named `webview.py` in the current directory. Renaming it to something else should fix the problem. [What renderer is used?](https://pywebview.flowrl.com/guide/faq#what-renderer-is-used) --------------------------------------------------------------------------------------- Set `PYWEBVIEW_LOG=debug` environment variable before running your programme. It will display used renderer in the first line of the program output. See available renderers [here](https://pywebview.flowrl.com/guide/renderer) [Terminal window receives key events on macOS](https://pywebview.flowrl.com/guide/faq#terminal-window-receives-key-events-on-macos) ------------------------------------------------------------------------------------------------------------------------------------ If you create a virtual environment using the built-in Python on macOS, a pywebview window will have issues with keyboard focus and Cmd+Tab. The issue can be avoided by using other Python installation. For example to use Python 3 via [Homebrew](https://brew.sh/) . brew install python3 virtualenv pywebview_env -p python3 [Frozen executable is too big](https://pywebview.flowrl.com/guide/faq#frozen-executable-is-too-big) ---------------------------------------------------------------------------------------------------- Big executable size is caused by packager picking up unnecessary dependencies. For example if you have `PyQt` installed but use Winforms on Windows, Pyinstaller will bundle both frameworks. To avoid this in Pyinstaller, use `--exclude-module` option to explicitly omit the module. [How do I get a full path of dropped files in `drop` event?](https://pywebview.flowrl.com/guide/faq#how-do-i-get-a-full-path-of-dropped-files-in-drop-event) ------------------------------------------------------------------------------------------------------------------------------------------------------------- Use `DOMEventHandler` and subscribe to the `drop` event. The file path information is stored in `event['dataTransfer']['files'][0]['pywebviewFullPath']` property of the event object. See [this example](https://pywebview.flowrl.com/examples/drag_drop) for details. --- # Web engine | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/web_engine#main-content) Web engine ========== 10/19/18Less than 1 minute * * * [Web engine](https://pywebview.flowrl.com/guide/web_engine#web-engine) ======================================================================= The following renderers are used on each platform | Platform | Code | Renderer | Provider | Browser compatibility | | --- | --- | --- | --- | --- | | Android | | WebKit | | Ever-green Chromium | | GTK | gtk | WebKit | WebKit2 (minimum version >2.2) | | | macOS | | WebKit | WebKit.WKWebView (bundled with OS) | | | QT | qt | WebKit | QtWebEngine / QtWebKit | | | Windows | edgechromium | Chromium | \> .NET Framework 4.6.2 and Edge Runtime installed | Ever-green Chromium | | Windows | cef | CEF | CEF Python | Chrome 66 | | Windows | mshtml | MSHTML | DEPRECATED Internet Explorer MSHTML | IE11 (Windows 10/8/7) | On Windows renderer is chosen in the following order: `edgechromium`, `mshtml`. `mshtml` is the only renderer that is guaranteed to be available on any system. Edge Runtime must be installed in order to use Edge Chromium on Windows. You can download it from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . Distribution guidelines are found [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) . To change a default renderer set either `PYWEBVIEW_GUI` environment variable or pass the rendered value to `webview.start(gui=code)` function parameter. Check for available values in the Code column from the table above. For example to use CEF on Windows export PYWEBVIEW_GUI=cef or import webview webview.start(gui='cef') If you wish to pass custom settings to CEF, refer to [this example](https://pywebview.flowrl.com/examples/cef) To force QT on Linux systems export PYWEBVIEW_GUI=qt or import webview webview.start(gui='qt') [Known issues and limitations](https://pywebview.flowrl.com/guide/web_engine#known-issues-and-limitations) ----------------------------------------------------------------------------------------------------------- [QtWebKit](https://pywebview.flowrl.com/guide/web_engine#qtwebkit) ------------------------------------------------------------------- * Debugging is not supported --- # Development | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/development#main-content) Development =========== 10/19/18About 2 min * * * [Development](https://pywebview.flowrl.com/contributing/development#development) ================================================================================= Before you get busy coding a new feature, create an issue and discuss the details in the issue tracker. [Environment set-up](https://pywebview.flowrl.com/contributing/development#environment-set-up) ----------------------------------------------------------------------------------------------- This guide assumes you have a [GitHub](https://github.com/) account, as well as [Python 3](https://python.org/) , [virtualenv](https://virtualenv.pypa.io/en/stable/) and [Git](https://git-scm.com/) installed. The guide is written for Bash, for Windows you can use for example Bash bundled with Git. * [Fork](https://github.com/r0x0r/pywebview/fork) _pywebview_ * Clone your forked repository git clone https://github.com//pywebview cd pywebview * Create a virtual environment virtualenv -p python3 venv source venv/bin/activate pip install -e ".[dev]" pip install pytest * Set up pre-commit hooks pre-commit install * Hello world python examples/simple_browser.py [Development work-flow](https://pywebview.flowrl.com/contributing/development#development-work-flow) ----------------------------------------------------------------------------------------------------- * Create and checkout a new branch git checkout -b new-branch master * Make your changes * Format and lint your code (this happens automatically with pre-commit) # Manual formatting and linting (optional, pre-commit does this automatically) ruff check --fix . ruff format . * Run tests pytest tests * Commit and push your work git add . git commit -m "Your commit message goes here" # Pre-commit hooks will run automatically git push -u origin new-branch * [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) [Testing](https://pywebview.flowrl.com/contributing/development#testing) ------------------------------------------------------------------------- pywebview uses [pytest](https://docs.pytest.org/en/latest/) for testing. To run all the tests in the project root directory pytest tests To run a specific test pytest tests/test_simple_browser.py Tests cover only trivial mistakes, syntax errors, exceptions and such. In other words there is no functional testing. Each test verifies that a pywebview window can be opened and exited without errors when run under different scenarios. Sometimes test fail / stuck randomly. The cause of the issue is not known, any help on resolving random fails is greatly appreciated. [Code Formatting and Linting](https://pywebview.flowrl.com/contributing/development#code-formatting-and-linting) ----------------------------------------------------------------------------------------------------------------- pywebview uses [Ruff](https://docs.astral.sh/ruff/) for code formatting and linting, along with [pre-commit](https://pre-commit.com/) hooks to automatically enforce code quality standards. ### [Pre-commit Hooks](https://pywebview.flowrl.com/contributing/development#pre-commit-hooks) Pre-commit hooks are automatically installed when you run `pre-commit install` during setup. They will run automatically before each commit to: * Fix import sorting * Apply consistent code formatting (single quotes, line length, etc.) * Check for large files, trailing whitespace, and YAML syntax * Run linting checks and apply automatic fixes where possible ### [Ruff Configuration](https://pywebview.flowrl.com/contributing/development#ruff-configuration) The project uses the following Ruff configuration (defined in `pyproject.toml`): * **Line length**: 100 characters * **Quote style**: Single quotes for strings * **Import sorting**: Enabled with `webview` as a known first-party package * **Target Python version**: 3.7+ * **Enabled rules**: Pyflakes (F), pycodestyle (E4, E7, E9), isort (I), and pyupgrade (UP) ### [Manual Formatting](https://pywebview.flowrl.com/contributing/development#manual-formatting) While pre-commit hooks handle formatting automatically, you can also run formatting manually: # Check for linting issues and apply fixes ruff check --fix . # Format code ruff format . # Run all pre-commit hooks manually pre-commit run --all-files ### [Code Style Guidelines](https://pywebview.flowrl.com/contributing/development#code-style-guidelines) * Use single quotes for strings (unless the string contains single quotes) * Maximum line length of 100 characters * Follow PEP 8 conventions * Use f-strings instead of `.format()` or `%` formatting where possible * Remove unused imports and variables * Use `isinstance()` instead of `type()` comparisons [Learning](https://pywebview.flowrl.com/contributing/development#learning) --------------------------------------------------------------------------- ### [Windows](https://pywebview.flowrl.com/contributing/development#windows) * [Windows Forms documentation](https://docs.microsoft.com/en-us/dotnet/framework/winforms/) * [Windows Forms API](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms) ### [macOS](https://pywebview.flowrl.com/contributing/development#macos) * [pyobjc](https://pythonhosted.org/pyobjc/) . Converting Objective C syntax to Python can be tricky at first. Be sure to check out the [pyobjc intro](https://pythonhosted.org/pyobjc/core/intro.html) . * [AppKit](https://developer.apple.com/documentation/appkit) * [WebKit](https://developer.apple.com/documentation/webkit) ### [Linux](https://pywebview.flowrl.com/contributing/development#linux) * [PyGObject API reference](https://lazka.github.io/pgi-docs/) ### [Qt](https://pywebview.flowrl.com/contributing/development#qt) * [Qt for Python Documentation](https://doc.qt.io/qtforpython-5/contents.html) * [Qt5 documentation](https://doc.qt.io/qt-5/index.html) * [PySide2 QtWidgets](https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/index.html) --- # Donating | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/donating.html#main-content) Donating ======== 10/19/18Less than 1 minute * * * [Donating](https://pywebview.flowrl.com/contributing/donating.html#donating) ============================================================================= [Recurrring pledge](https://pywebview.flowrl.com/contributing/donating.html#recurrring-pledge) ----------------------------------------------------------------------------------------------- Recurring pledges come perks, like getting email support or featuring your name or logo in the project repository [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [One-time donations](https://pywebview.flowrl.com/contributing/donating.html#one-time-donations) ------------------------------------------------------------------------------------------------- We accept donations via Paypal [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # Bug reporting | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/bug_reporting#main-content) Bug reporting ============= 10/19/18Less than 1 minute * * * [Bug reporting](https://pywebview.flowrl.com/contributing/bug_reporting#bug-reporting) ======================================================================================= If you think you found a bug, verify following steps first 1. Does the bug occur in a default browser? If so, the problem is with your code, not pywebview 2. Are you using the latest master? Bug fixes are merged into the master and it may take a while until a new release is deployed to Pypi. 3. Has it been [reported](https://github.com/r0x0r/pywebview/issues) already? If you verified all the three points and are sure that the issue is caused by pywebview, feel free to submit a new issue. Please remember to specify under which operating system the bug occurs, as well as with other relevant information. In case of Linux, specify a distro you are using. --- # Introducing pywebview 3.0 | pywebview [Skip to main content](https://pywebview.flowrl.com/blog/pywebview3#main-content) Introducing pywebview 3.0 ========================= 7/10/19About 3 min * * * ![pywebview 3.0](https://pywebview.flowrl.com/assets/pywebview3-BdGmmgRv.png) [Introducing pywebview 3.0](https://pywebview.flowrl.com/blog/pywebview3#introducing-pywebview-3-0) ==================================================================================================== I am happy to announce the release of _pywebview 3.0_. _pywebview_ lets you to build GUI for your Python program using HTML, CSS and Javascript, while doing its best hiding the fact that the GUI is built using a browser. Think of _pywebview_ as lightweight Electron for Python. Unlike Electron, _pywebview_ does not bundle a web renderer, but instead relies on a rendered provided by operating system. _Sidenote: bundling a renderer is still an option though, as in case of CEF_. If you are new here, head over to [usage guide](https://pywebview.flowrl.com/guide/usage) , [API reference](https://pywebview.flowrl.com/api.html) , [examples](https://pywebview.flowrl.com/examples) and our very own [TODOs app](https://github.com/r0x0r/pywebview/tree/master/examples/todos) . Oh and _pywebview_ can be installed with pip install pywebview [What's new?](https://pywebview.flowrl.com/blog/pywebview3#what-s-new) ----------------------------------------------------------------------- Version 3.0 is the first version that is not compatible with previous versions. Multi-window support introduced in 2.x resulted in some questionable architectural decisions, which now have been resolved and hopefully make more sense. Notable changes include: ### [webview.start()](https://pywebview.flowrl.com/blog/pywebview3#webview-start) The biggest change is introduction of window objects and `webview.start()` function that starts a GUI loop. Previously GUI loop was started by the first call of `webview.create_window()`. Hence `create_window` had in fact two functions: creating a window and starting a GUI loop. To make things more confusing the first call to `create_window` was blocking, while subsequent calls from subthreads were not. To make things more straightforward, `create_window` now creates a window and returns a window object, no matter how many times you call it. The function is always non-blocking too. Bear in mind that until GUI loop is started, no windows are displayed. Using new API, hello world in _pywebview_ looks like this: import webview window = webview.create_window('Hello world', 'https://pywebview.flowrl.com/hello') webview.start() `webview.start` also provides a convenient way to execute thread specific code after GUI loop is started, so no more threading boilerplate. import webview def change_title(window): window.change_title('pywebview whoa') window = webview.create_window('pywebview wow', 'https://pywebview.flowrl.com/hello') webview.start(change_title, window) ### [Window object](https://pywebview.flowrl.com/blog/pywebview3#window-object) All the functions related to window management and web content have been moved to a window object as returned by `webview.create_window`. For example `webview.load_html` became `window.load_html` as in: import webview def load_html(window): window.load_html('

pywebview wow!

') window = webview.create_window('pywebview wow') webview.start(load_html, window) ### [Built-in HTTP server](https://pywebview.flowrl.com/blog/pywebview3#built-in-http-server) _pywebview_ now provides its own HTTP server for serving static local files. For obfuscation purposes server is started on a random port. import webview window = webview.create_window('pywebview wow', 'assets/index.html') webview.start(http_server=True) ### [Events](https://pywebview.flowrl.com/blog/pywebview3#events) 3.0 introduces a new event system that lets to subscribe/unsubscribe to events. Currently `shown` and `loaded` events are implemented. Event objects are provided by a window object. See [events example](https://pywebview.flowrl.com/examples/events) for usage details. ### [Edge support](https://pywebview.flowrl.com/blog/pywebview3#edge-support) Windows now provides support for EdgeHTML. EdgeHTML is automatically chosen if your system requirements are met (.NET 4.6.2 and Windows 10 1803). Unfortunately accessing local files is not currently possible with EdgeHTML, so you must use a HTTP server. If you wish for some reason to force MSHTML, you can `webview.start(gui='mshtml')`. ### [create\_window now can load html directly](https://pywebview.flowrl.com/blog/pywebview3#create-window-now-can-load-html-directly) import webview window = webview.create_window('pywebview wow', html='

pywebview wow!

') webview.start() If both url and html parameters are provided, html takes precedence. ### [get\_elements](https://pywebview.flowrl.com/blog/pywebview3#get-elements) You can now retrieve DOM nodes by using `window.get_elements(selector)` function. Nodes are serialized using [domJSON](https://github.com/azaslavsky/domJSON) library. [Example](https://pywebview.flowrl.com/examples/get_elements) ### [Config is gone](https://pywebview.flowrl.com/blog/pywebview3#config-is-gone) `webview.config` is no more. To set a GUI renderer, use the `gui` parameter to `webview.start` ### [confirm\_quit is now confirm\_close](https://pywebview.flowrl.com/blog/pywebview3#confirm-quit-is-now-confirm-close) E.g. `webview.create_window('Window', confirm_close=True)` [Support the project](https://pywebview.flowrl.com/blog/pywebview3#support-the-project) ======================================================================================== _pywebview_ is a small project with limited resources, any help is welcome. PRs, documentation, research, anything goes. Having said that commits are preferred over comments. Check out the [contributing guide](https://pywebview.flowrl.com/contributing) to get started. If you find _pywebview_ useful, please support it. We offer donations via Patreon and Open Collective, as well as one-time Paypal donations. If you represent a company, consider becoming a sponsor to get exposure for your company and connect with Python developers. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # Documentation | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/documentation#main-content) Documentation ============= 10/19/18Less than 1 minute * * * [Documentation](https://pywebview.flowrl.com/contributing/documentation#documentation) ======================================================================================= One way to contribute is to improve documentation on this side. Each page has a 'Help us improve this page' link at the bottom of the page. By clicking the link you can create a pull request with your changes. You need a Github account to edit pages. --- # 5.0 has landed | pywebview [Skip to main content](https://pywebview.flowrl.com/blog/pywebview5#main-content) 5.0 has landed ============== 3/10/24About 2 min * * * ![pywebview](https://pywebview.flowrl.com/logo-no-text.png) [5.0 has landed](https://pywebview.flowrl.com/blog/pywebview5#_5-0-has-landed) =============================================================================== I am happy to announce the release of _pywebview 5_. The new version introduces three major features: Android support, DOM manipulation and application settings. For a full changelog, see [here](https://pywebview.flowrl.com/changelog) . If you are not familiar with _pywebview_, it is a Python library that lets you to build GUI for your Python program using HTML, CSS and Javascript. Available for Windows, macOS, Linux and Android. _pywebview_ can be installed with pip install pywebview [Android](https://pywebview.flowrl.com/blog/pywebview5#android) ---------------------------------------------------------------- You can now run your _pywebview_ on Android devices. Mobile experience brings its own limitations though. There is no window manipulation, multi-window or file dialog support. Otherwise, it works same as on other platforms. Head over to [Freezing](https://pywebview.flowrl.com/guide/freezing) for details how to package your app for Android. [DOM](https://pywebview.flowrl.com/blog/pywebview5#dom) -------------------------------------------------------- With DOM support you can perform jQuery like DOM manipulation, traversal and event handling straight from Python. You can access and modify element's attributes, style and classes as well. A new `Element` object represents a DOM node in Python. It is returned by `window.dom.get_element`, `window.dom.get_elements` and `window.dom.create_element`. Body, document and window are conviently exposed as `window.dom.body`, `window.dom.document` and `window.dom.body` respectively. The new Javascript serializer allows you to serialize more Javascript object types and handles circular dependencies, so Here is a toy example of the new API. window.dom.document.events.scroll += lambda e: print(window.dom.window.node['scrollY']) button = window.dom.create_element('', window.dom.body) button.style['width'] = '200px' button.attributes = { 'disabled': False } button.events.click += click_handler button.classes.toggle('hidden') See [events](https://pywebview.flowrl.com/examples/dom_events) , [manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) , [traversal](https://pywebview.flowrl.com/examples/dom_traversal) for complete examples. A much requested feature is a full file path support for drag and drop operations. _pywebview_ enhances `DropEvent` by introducing `event['dataTransfer']['files'][0]['pywebviewFullPath']` that has full absolute path of a dropped file(s). The full path is available only on Python's side. [Application settings](https://pywebview.flowrl.com/blog/pywebview5#application-settings) ------------------------------------------------------------------------------------------ _pywebview_ is rather opinionated on how default experience should be. Over the years, I have received numerous feature requests asking to change the default behaviour, which is now possible with application settings. The new version introduces `webview.settings` dictionary with following options. webview.settings = { 'ALLOW_DOWNLOADS': False, # Allow file downloads 'ALLOW_FILE_URLS': True, # Allow access to file:// urls 'OPEN_EXTERNAL_LINKS_IN_BROWSER': True, # Open target=_blank links in an external browser 'OPEN_DEVTOOLS_IN_DEBUG': True, # Automatically open devtools when `start(debug=True)`. } Application settings must be set before invoking `webview.start()` to have an effect. [Learn more](https://pywebview.flowrl.com/blog/pywebview5#learn-more) ---------------------------------------------------------------------- Interested in learning more? Head over to [usage guide](https://pywebview.flowrl.com/guide/usage) , [API reference](https://pywebview.flowrl.com/api.html) and [examples](https://pywebview.flowrl.com/examples) [Support the project](https://pywebview.flowrl.com/blog/pywebview5#support-the-project) ---------------------------------------------------------------------------------------- _pywebview_ is largely an one-man project, which gets updated sporadically whenever time permits. Any help is appreciated and the best way to contribute is submitting a pull request. Bug fixes are always welcomed. If you wish to submit a new feature, please create an issue and discuss it beforehand. Check out the [contributing guide](https://pywebview.flowrl.com/contributing) to get started. If you find _pywebview_ useful and would like to see it developed in the future, considering sponsoring it. If you represent a company, consider becoming a sponsor to get exposure for your company and connect with Python developers. [![Sponsor on Github](https://pywebview.flowrl.com/github_sponsor_button.png)](https://github.com/sponsors/r0x0r) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # Menu | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/menu#main-content) Menu ==== 4/23/22Less than 1 minute * * * [Menu](https://pywebview.flowrl.com/examples/menu#menu) ======================================================== Create an application menu. import webview from webview.menu import Menu, MenuAction, MenuSeparator def change_active_window_content(): active_window = webview.active_window() if active_window: active_window.load_html('

You changed this window!

') def click_me(): active_window = webview.active_window() if active_window: active_window.load_html('

You clicked me!

') def test(): active_window = webview.active_window() if active_window: active_window.load_html('

This is a test!

') def do_nothing(): pass def say_this_is_window_2(): active_window = webview.active_window() if active_window: active_window.load_html('

This is window 2

') def open_save_file_dialog(): active_window = webview.active_window() active_window.create_file_dialog( webview.FileDialog.SAVE, directory='/', save_filename='test.file' ) def open_preferences(): active_window = webview.active_window() if active_window: active_window.load_html( '

Preferences

App preferences would open here (macOS app menu)

' ) def check_for_updates(): active_window = webview.active_window() if active_window: active_window.load_html( '

Check for Updates

Checking for updates... (macOS app menu)

' ) if __name__ == '__main__': # App menu items (macOS only - appears between About and Services) # On other platforms, this menu is ignored macos_app_menu = Menu( '__app__', [\ MenuAction('Preferences...', open_preferences),\ MenuSeparator(),\ MenuAction('Check for Updates', check_for_updates),\ ], ) window_menu = [Menu('Window', [MenuAction('Test', test)])] app_menu = [\ macos_app_menu, # macOS app menu items\ Menu(\ 'Menu 1',\ [\ MenuAction('Change Active Window Content', change_active_window_content),\ MenuSeparator(),\ Menu(\ 'Random',\ [\ MenuAction('Click Me', click_me),\ MenuAction('File Dialog', open_save_file_dialog),\ ],\ ),\ ],\ ),\ Menu('Menu 2', [MenuAction('This will do nothing', do_nothing)]),\ ] window_1 = webview.create_window( 'Application Menu Example', 'https://pywebview.flowrl.com/hello' ) window_2 = webview.create_window( 'Window Menu Example', html='

Another window to test application menu

', menu=window_menu, ) webview.start(menu=app_menu) --- # 6.0 is here | pywebview [Skip to main content](https://pywebview.flowrl.com/blog/pywebview6#main-content) 6.0 is here =========== 8/8/25About 3 min * * * ![pywebview](https://pywebview.flowrl.com/logo-no-text.png) [6.0 is here](https://pywebview.flowrl.com/blog/pywebview6#_6-0-is-here) ========================================================================= I am excited to announce the release of _pywebview 6_. The new version introduces powerful state management, network event handling, and significant improvements to Android support. For a complete changelog, see [here](https://pywebview.flowrl.com/changelog) . If you are not familiar with _pywebview_, it's a lightweight Python framework for building modern desktop applications with web technologies. Unlike heavyweight alternatives, _pywebview_ leverages your system's native webview, resulting in smaller binaries and better performance. Write your UI once in HTML, CSS, and JavaScript, then deploy across Windows, macOS, Linux, and Android with the full power of Python at your fingertips. _pywebview_ can be installed with pip install pywebview [Shared State Management](https://pywebview.flowrl.com/blog/pywebview6#shared-state-management) ------------------------------------------------------------------------------------------------ One of the most exciting features in version 6 is the new shared state management via the `window.state` object. This revolutionary feature automatically synchronizes state between Javascript and Python, eliminating the need for manual data synchronization. # In Python window.state.user_name = "Test" // In Javascript - automatically updated! console.log(window.pywebview.state.user_name); // "Test" This bidirectional synchronization makes building complex applications much simpler, as you no longer need to manually pass data between Python and Javascript. Currenlty state syncronization is limited to top-level properties. If you want to synchronize nested objects, you need to reassign the entire object. For example: # In Python window.state.user_settings = {"theme": "dark", "notifications": True} // In Javascript - automatically updated! console.log(window.pywebview.state.user_settings); // {"theme": "dark", "notifications": True} window.pywebview.state.user_settings = {"theme": "light", "notifications": False} // Updates Python side too [New events](https://pywebview.flowrl.com/blog/pywebview6#new-events) ---------------------------------------------------------------------- _pywebview 6_ introduces powerful network monitoring capabilities with the new `request_sent` and `response_received` events. These events are fired whenever HTTP requests are made, giving you full visibility into your application's network activity. Request headers can be modified before sending, and you can inspect responses as they arrive. Response header modification is not supported. def on_request_sent(request): print(f"Sending request to: {request['url']}") # Modify request headers before sending request['headers']['Authorization'] = f"Bearer {get_auth_token()}" def on_response_received(response): print(f"Received response: {response['status_code']}") window.events.request_sent += on_request_sent window.events.response_received += on_response_received Another new event is `initialized`, which is fired when the GUI library or webview renderer is chosen, before the window is created. This allows you to customize behavior based on the selected renderer or abort execution altogether by returning `False` from the event handler. def on_initialized(renderer): print(f"Initialized with renderer: {renderer}") window.events.initialized += on_initialized [Enhanced Android Support](https://pywebview.flowrl.com/blog/pywebview6#enhanced-android-support) -------------------------------------------------------------------------------------------------- Android support receives a major upgrade with a new Kivyless implementation that significantly improves startup time and reduces package size. Additionally, Android apps now support fullscreen mode, bringing mobile experience closer to native apps. Furthermore Android now has a new dedicated test suite found in `tests/android`. [Window-Specific Menus](https://pywebview.flowrl.com/blog/pywebview6#window-specific-menus) -------------------------------------------------------------------------------------------- You can now create custom menus for individual windows, giving you more control over the user interface (not supported on GTK with Unity) menu = webview.menu.Menu([\ webview.menu.MenuAction('File', [\ webview.menu.MenuAction('New', new_file),\ webview.menu.MenuSeparator(),\ webview.menu.MenuAction('Exit', exit_app)\ ])\ ]) window = webview.create_window('My App', 'index.html', menu=menu) [Modern API Improvements](https://pywebview.flowrl.com/blog/pywebview6#modern-api-improvements) ------------------------------------------------------------------------------------------------ Version 6 includes several breaking changes that modernize the API and removes deprecated features: * File dialog constants are now part of the `webview.FileDialog` enum (`SAVE`, `LOAD`, `FOLDER`) * `webview.DRAG_REGION_SELECTOR` moved to `webview.settings['webview.DRAG_REGION_SELECTOR']` * Deprecated DOM functions are removed in favor of the modern `window.dom` API [Platform-Specific Enhancements](https://pywebview.flowrl.com/blog/pywebview6#platform-specific-enhancements) -------------------------------------------------------------------------------------------------------------- * **Windows**: Dark mode support with automatic theme detection * **macOS**: Option to hide default menus and better Javascript prompt handling * **All platforms**: Improved screen coordinate handling and better SSL support [Learn more](https://pywebview.flowrl.com/blog/pywebview6#learn-more) ---------------------------------------------------------------------- Ready to explore _pywebview 6_? Check out the [usage guide](https://pywebview.flowrl.com/guide/usage) , [API reference](https://pywebview.flowrl.com/guide/api.html) and [examples](https://pywebview.flowrl.com/examples) to get started with the new features. [Support the project](https://pywebview.flowrl.com/blog/pywebview6#support-the-project) ---------------------------------------------------------------------------------------- _pywebview_ continues to be primarily a one-person project, updated when time allows. Your contributions make a real difference! The best way to help is by submitting pull requests - bug fixes are always welcome, and for new features, please create an issue to discuss first. Check out the [contributing guide](https://pywebview.flowrl.com/contributing) to get started. If _pywebview_ has been useful for your projects and you'd like to see continued development, consider sponsoring the project. Companies can become sponsors to gain exposure and connect with the Python developer community. [![Sponsor on Github](https://pywebview.flowrl.com/github_sponsor_button.png)](https://github.com/sponsors/r0x0r) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # Installation | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/installation.html#main-content) Installation ============ 10/19/18About 1 min * * * [Installation](https://pywebview.flowrl.com/guide/installation.html#installation) ================================================================================== pip install pywebview This will install _pywebview_ with default dependencies for each platform. On Linux you have to explicitly choose between QT and GTK. pip install pywebview[gtk] or # This will install PyQT6 pip install pywebview[qt] Other QT related options are `pywebview[qt5]`, `pywebview[pyside2]` and `pywebview[pyside6]` Other optional dependencies are `pywebview[android]`, `pywebview[cef]` and `pywebview[ssl]`. CEF is available only for Windows. `ssl` option installs a `cryptography` package, which is needed for using https in local HTTP server. [Dependencies](https://pywebview.flowrl.com/guide/installation.html#dependencies) ---------------------------------------------------------------------------------- ### [Windows](https://pywebview.flowrl.com/guide/installation.html#windows) [pythonnet](https://github.com/pythonnet/pythonnet) (requires > .NET 4.0) To use with the latest Chromium you need [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . If you plan to distribute your software, check out [distribution guidelines](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) too. To use with CEF you need [cefpython](https://github.com/cztomczak/cefpython/) QT can be used on Windows as well. ### [macOS](https://pywebview.flowrl.com/guide/installation.html#macos) [pyobjc](https://pythonhosted.org/pyobjc/) `PyObjC` comes preinstalled with the Python bundled in macOS. For a stand-alone Python installation you have to install it separately. You do not need the entire `PyObjC` package, these packages suffice pyobjc-core pyobjc-framework-Cocoa pyobjc-framework-Quartz pyobjc-framework-WebKit pyobjc-framework-security You can also use `QT` on macOS. ### [Linux](https://pywebview.flowrl.com/guide/installation.html#linux) `pip install pywebview[qt]` should take care of QT dependencies. If it does not work or you would like to use GTK, you may try these recipes. To install QtWebChannel on Debian-based systems (more modern, preferred) sudo apt install python3-pyqt5 python3-pyqt5.qtwebengine python3-pyqt5.qtwebchannel libqt5webkit5-dev To install QtWebKit (legacy, but available for more platforms). sudo apt install python3-pyqt5 python3-pyqt5.qtwebkit python-pyqt5 python-pyqt5.qtwebkit libqt5webkit5-dev [PyGObject](https://pygobject.readthedocs.io/en/latest/) is used with GTK. To install dependencies on Ubuntu, use sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-webkit2-4.1 For other distributions, consult the [PyGObject documentation](https://pygobject.readthedocs.io/en/latest/getting_started.html) Note that WebKit2 version 2.22 or greater is required. Warning Starting from Ubuntu Disco Dingo _pywebview_ can be installed via `apt` on Debian based system as `python3-webview` or `python-pywebview`. Ubuntu's distribution lags a few versions behind. If you wish to stay up-to-date, consider installing via `pip`. ### [Android](https://pywebview.flowrl.com/guide/installation.html#android) For Android development, refer to Kivy's [packaging instructions for Android](https://kivy.org/doc/stable-1.10.1/guide/packaging-android.html) . --- # Blog | pywebview [#](https://pywebview.flowrl.com/3.7/blog/#blog) Blog ====================================================== ### [#](https://pywebview.flowrl.com/3.7/blog/#_2019-07-11-introducing-pywebview-3-0) 2019-07-11 Introducing pywebview 3.0 _pywebview_ has reached version 3.0 and has a number of breaking changes. [Read more](https://pywebview.flowrl.com/3.7/blog/pywebview3) --- # Documentation | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/documentation.html#main-content) Documentation ============= 10/19/18Less than 1 minute * * * [Documentation](https://pywebview.flowrl.com/contributing/documentation.html#documentation) ============================================================================================ One way to contribute is to improve documentation on this side. Each page has a 'Help us improve this page' link at the bottom of the page. By clicking the link you can create a pull request with your changes. You need a Github account to edit pages. --- # Bug reporting | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/bug_reporting.html#main-content) Bug reporting ============= 10/19/18Less than 1 minute * * * [Bug reporting](https://pywebview.flowrl.com/contributing/bug_reporting.html#bug-reporting) ============================================================================================ If you think you found a bug, verify following steps first 1. Does the bug occur in a default browser? If so, the problem is with your code, not pywebview 2. Are you using the latest master? Bug fixes are merged into the master and it may take a while until a new release is deployed to Pypi. 3. Has it been [reported](https://github.com/r0x0r/pywebview/issues) already? If you verified all the three points and are sure that the issue is caused by pywebview, feel free to submit a new issue. Please remember to specify under which operating system the bug occurs, as well as with other relevant information. In case of Linux, specify a distro you are using. --- # Development | pywebview [Skip to main content](https://pywebview.flowrl.com/contributing/development.html#main-content) Development =========== 10/19/18About 2 min * * * [Development](https://pywebview.flowrl.com/contributing/development.html#development) ====================================================================================== Before you get busy coding a new feature, create an issue and discuss the details in the issue tracker. [Environment set-up](https://pywebview.flowrl.com/contributing/development.html#environment-set-up) ---------------------------------------------------------------------------------------------------- This guide assumes you have a [GitHub](https://github.com/) account, as well as [Python 3](https://python.org/) , [virtualenv](https://virtualenv.pypa.io/en/stable/) and [Git](https://git-scm.com/) installed. The guide is written for Bash, for Windows you can use for example Bash bundled with Git. * [Fork](https://github.com/r0x0r/pywebview/fork) _pywebview_ * Clone your forked repository git clone https://github.com//pywebview cd pywebview * Create a virtual environment virtualenv -p python3 venv source venv/bin/activate pip install -e ".[dev]" pip install pytest * Set up pre-commit hooks pre-commit install * Hello world python examples/simple_browser.py [Development work-flow](https://pywebview.flowrl.com/contributing/development.html#development-work-flow) ---------------------------------------------------------------------------------------------------------- * Create and checkout a new branch git checkout -b new-branch master * Make your changes * Format and lint your code (this happens automatically with pre-commit) # Manual formatting and linting (optional, pre-commit does this automatically) ruff check --fix . ruff format . * Run tests pytest tests * Commit and push your work git add . git commit -m "Your commit message goes here" # Pre-commit hooks will run automatically git push -u origin new-branch * [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) [Testing](https://pywebview.flowrl.com/contributing/development.html#testing) ------------------------------------------------------------------------------ pywebview uses [pytest](https://docs.pytest.org/en/latest/) for testing. To run all the tests in the project root directory pytest tests To run a specific test pytest tests/test_simple_browser.py Tests cover only trivial mistakes, syntax errors, exceptions and such. In other words there is no functional testing. Each test verifies that a pywebview window can be opened and exited without errors when run under different scenarios. Sometimes test fail / stuck randomly. The cause of the issue is not known, any help on resolving random fails is greatly appreciated. [Code Formatting and Linting](https://pywebview.flowrl.com/contributing/development.html#code-formatting-and-linting) ---------------------------------------------------------------------------------------------------------------------- pywebview uses [Ruff](https://docs.astral.sh/ruff/) for code formatting and linting, along with [pre-commit](https://pre-commit.com/) hooks to automatically enforce code quality standards. ### [Pre-commit Hooks](https://pywebview.flowrl.com/contributing/development.html#pre-commit-hooks) Pre-commit hooks are automatically installed when you run `pre-commit install` during setup. They will run automatically before each commit to: * Fix import sorting * Apply consistent code formatting (single quotes, line length, etc.) * Check for large files, trailing whitespace, and YAML syntax * Run linting checks and apply automatic fixes where possible ### [Ruff Configuration](https://pywebview.flowrl.com/contributing/development.html#ruff-configuration) The project uses the following Ruff configuration (defined in `pyproject.toml`): * **Line length**: 100 characters * **Quote style**: Single quotes for strings * **Import sorting**: Enabled with `webview` as a known first-party package * **Target Python version**: 3.7+ * **Enabled rules**: Pyflakes (F), pycodestyle (E4, E7, E9), isort (I), and pyupgrade (UP) ### [Manual Formatting](https://pywebview.flowrl.com/contributing/development.html#manual-formatting) While pre-commit hooks handle formatting automatically, you can also run formatting manually: # Check for linting issues and apply fixes ruff check --fix . # Format code ruff format . # Run all pre-commit hooks manually pre-commit run --all-files ### [Code Style Guidelines](https://pywebview.flowrl.com/contributing/development.html#code-style-guidelines) * Use single quotes for strings (unless the string contains single quotes) * Maximum line length of 100 characters * Follow PEP 8 conventions * Use f-strings instead of `.format()` or `%` formatting where possible * Remove unused imports and variables * Use `isinstance()` instead of `type()` comparisons [Learning](https://pywebview.flowrl.com/contributing/development.html#learning) -------------------------------------------------------------------------------- ### [Windows](https://pywebview.flowrl.com/contributing/development.html#windows) * [Windows Forms documentation](https://docs.microsoft.com/en-us/dotnet/framework/winforms/) * [Windows Forms API](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms) ### [macOS](https://pywebview.flowrl.com/contributing/development.html#macos) * [pyobjc](https://pythonhosted.org/pyobjc/) . Converting Objective C syntax to Python can be tricky at first. Be sure to check out the [pyobjc intro](https://pythonhosted.org/pyobjc/core/intro.html) . * [AppKit](https://developer.apple.com/documentation/appkit) * [WebKit](https://developer.apple.com/documentation/webkit) ### [Linux](https://pywebview.flowrl.com/contributing/development.html#linux) * [PyGObject API reference](https://lazka.github.io/pgi-docs/) ### [Qt](https://pywebview.flowrl.com/contributing/development.html#qt) * [Qt for Python Documentation](https://doc.qt.io/qtforpython-5/contents.html) * [Qt5 documentation](https://doc.qt.io/qt-5/index.html) * [PySide2 QtWidgets](https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/index.html) --- # Introducing pywebview 3.0 | pywebview [Skip to main content](https://pywebview.flowrl.com/blog/pywebview3.html#main-content) Introducing pywebview 3.0 ========================= 7/10/19About 3 min * * * ![pywebview 3.0](https://pywebview.flowrl.com/assets/pywebview3-BdGmmgRv.png) [Introducing pywebview 3.0](https://pywebview.flowrl.com/blog/pywebview3.html#introducing-pywebview-3-0) ========================================================================================================= I am happy to announce the release of _pywebview 3.0_. _pywebview_ lets you to build GUI for your Python program using HTML, CSS and Javascript, while doing its best hiding the fact that the GUI is built using a browser. Think of _pywebview_ as lightweight Electron for Python. Unlike Electron, _pywebview_ does not bundle a web renderer, but instead relies on a rendered provided by operating system. _Sidenote: bundling a renderer is still an option though, as in case of CEF_. If you are new here, head over to [usage guide](https://pywebview.flowrl.com/guide/usage) , [API reference](https://pywebview.flowrl.com/api.html) , [examples](https://pywebview.flowrl.com/examples) and our very own [TODOs app](https://github.com/r0x0r/pywebview/tree/master/examples/todos) . Oh and _pywebview_ can be installed with pip install pywebview [What's new?](https://pywebview.flowrl.com/blog/pywebview3.html#what-s-new) ---------------------------------------------------------------------------- Version 3.0 is the first version that is not compatible with previous versions. Multi-window support introduced in 2.x resulted in some questionable architectural decisions, which now have been resolved and hopefully make more sense. Notable changes include: ### [webview.start()](https://pywebview.flowrl.com/blog/pywebview3.html#webview-start) The biggest change is introduction of window objects and `webview.start()` function that starts a GUI loop. Previously GUI loop was started by the first call of `webview.create_window()`. Hence `create_window` had in fact two functions: creating a window and starting a GUI loop. To make things more confusing the first call to `create_window` was blocking, while subsequent calls from subthreads were not. To make things more straightforward, `create_window` now creates a window and returns a window object, no matter how many times you call it. The function is always non-blocking too. Bear in mind that until GUI loop is started, no windows are displayed. Using new API, hello world in _pywebview_ looks like this: import webview window = webview.create_window('Hello world', 'https://pywebview.flowrl.com/hello') webview.start() `webview.start` also provides a convenient way to execute thread specific code after GUI loop is started, so no more threading boilerplate. import webview def change_title(window): window.change_title('pywebview whoa') window = webview.create_window('pywebview wow', 'https://pywebview.flowrl.com/hello') webview.start(change_title, window) ### [Window object](https://pywebview.flowrl.com/blog/pywebview3.html#window-object) All the functions related to window management and web content have been moved to a window object as returned by `webview.create_window`. For example `webview.load_html` became `window.load_html` as in: import webview def load_html(window): window.load_html('

pywebview wow!

') window = webview.create_window('pywebview wow') webview.start(load_html, window) ### [Built-in HTTP server](https://pywebview.flowrl.com/blog/pywebview3.html#built-in-http-server) _pywebview_ now provides its own HTTP server for serving static local files. For obfuscation purposes server is started on a random port. import webview window = webview.create_window('pywebview wow', 'assets/index.html') webview.start(http_server=True) ### [Events](https://pywebview.flowrl.com/blog/pywebview3.html#events) 3.0 introduces a new event system that lets to subscribe/unsubscribe to events. Currently `shown` and `loaded` events are implemented. Event objects are provided by a window object. See [events example](https://pywebview.flowrl.com/examples/events) for usage details. ### [Edge support](https://pywebview.flowrl.com/blog/pywebview3.html#edge-support) Windows now provides support for EdgeHTML. EdgeHTML is automatically chosen if your system requirements are met (.NET 4.6.2 and Windows 10 1803). Unfortunately accessing local files is not currently possible with EdgeHTML, so you must use a HTTP server. If you wish for some reason to force MSHTML, you can `webview.start(gui='mshtml')`. ### [create\_window now can load html directly](https://pywebview.flowrl.com/blog/pywebview3.html#create-window-now-can-load-html-directly) import webview window = webview.create_window('pywebview wow', html='

pywebview wow!

') webview.start() If both url and html parameters are provided, html takes precedence. ### [get\_elements](https://pywebview.flowrl.com/blog/pywebview3.html#get-elements) You can now retrieve DOM nodes by using `window.get_elements(selector)` function. Nodes are serialized using [domJSON](https://github.com/azaslavsky/domJSON) library. [Example](https://pywebview.flowrl.com/examples/get_elements) ### [Config is gone](https://pywebview.flowrl.com/blog/pywebview3.html#config-is-gone) `webview.config` is no more. To set a GUI renderer, use the `gui` parameter to `webview.start` ### [confirm\_quit is now confirm\_close](https://pywebview.flowrl.com/blog/pywebview3.html#confirm-quit-is-now-confirm-close) E.g. `webview.create_window('Window', confirm_close=True)` [Support the project](https://pywebview.flowrl.com/blog/pywebview3.html#support-the-project) ============================================================================================= _pywebview_ is a small project with limited resources, any help is welcome. PRs, documentation, research, anything goes. Having said that commits are preferred over comments. Check out the [contributing guide](https://pywebview.flowrl.com/contributing) to get started. If you find _pywebview_ useful, please support it. We offer donations via Patreon and Open Collective, as well as one-time Paypal donations. If you represent a company, consider becoming a sponsor to get exposure for your company and connect with Python developers. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # 5.0 has landed | pywebview [Skip to main content](https://pywebview.flowrl.com/blog/pywebview5.html#main-content) 5.0 has landed ============== 3/10/24About 2 min * * * ![pywebview](https://pywebview.flowrl.com/logo-no-text.png) [5.0 has landed](https://pywebview.flowrl.com/blog/pywebview5.html#_5-0-has-landed) ==================================================================================== I am happy to announce the release of _pywebview 5_. The new version introduces three major features: Android support, DOM manipulation and application settings. For a full changelog, see [here](https://pywebview.flowrl.com/changelog) . If you are not familiar with _pywebview_, it is a Python library that lets you to build GUI for your Python program using HTML, CSS and Javascript. Available for Windows, macOS, Linux and Android. _pywebview_ can be installed with pip install pywebview [Android](https://pywebview.flowrl.com/blog/pywebview5.html#android) --------------------------------------------------------------------- You can now run your _pywebview_ on Android devices. Mobile experience brings its own limitations though. There is no window manipulation, multi-window or file dialog support. Otherwise, it works same as on other platforms. Head over to [Freezing](https://pywebview.flowrl.com/guide/freezing) for details how to package your app for Android. [DOM](https://pywebview.flowrl.com/blog/pywebview5.html#dom) ------------------------------------------------------------- With DOM support you can perform jQuery like DOM manipulation, traversal and event handling straight from Python. You can access and modify element's attributes, style and classes as well. A new `Element` object represents a DOM node in Python. It is returned by `window.dom.get_element`, `window.dom.get_elements` and `window.dom.create_element`. Body, document and window are conviently exposed as `window.dom.body`, `window.dom.document` and `window.dom.body` respectively. The new Javascript serializer allows you to serialize more Javascript object types and handles circular dependencies, so Here is a toy example of the new API. window.dom.document.events.scroll += lambda e: print(window.dom.window.node['scrollY']) button = window.dom.create_element('', window.dom.body) button.style['width'] = '200px' button.attributes = { 'disabled': False } button.events.click += click_handler button.classes.toggle('hidden') See [events](https://pywebview.flowrl.com/examples/dom_events) , [manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) , [traversal](https://pywebview.flowrl.com/examples/dom_traversal) for complete examples. A much requested feature is a full file path support for drag and drop operations. _pywebview_ enhances `DropEvent` by introducing `event['dataTransfer']['files'][0]['pywebviewFullPath']` that has full absolute path of a dropped file(s). The full path is available only on Python's side. [Application settings](https://pywebview.flowrl.com/blog/pywebview5.html#application-settings) ----------------------------------------------------------------------------------------------- _pywebview_ is rather opinionated on how default experience should be. Over the years, I have received numerous feature requests asking to change the default behaviour, which is now possible with application settings. The new version introduces `webview.settings` dictionary with following options. webview.settings = { 'ALLOW_DOWNLOADS': False, # Allow file downloads 'ALLOW_FILE_URLS': True, # Allow access to file:// urls 'OPEN_EXTERNAL_LINKS_IN_BROWSER': True, # Open target=_blank links in an external browser 'OPEN_DEVTOOLS_IN_DEBUG': True, # Automatically open devtools when `start(debug=True)`. } Application settings must be set before invoking `webview.start()` to have an effect. [Learn more](https://pywebview.flowrl.com/blog/pywebview5.html#learn-more) --------------------------------------------------------------------------- Interested in learning more? Head over to [usage guide](https://pywebview.flowrl.com/guide/usage) , [API reference](https://pywebview.flowrl.com/api.html) and [examples](https://pywebview.flowrl.com/examples) [Support the project](https://pywebview.flowrl.com/blog/pywebview5.html#support-the-project) --------------------------------------------------------------------------------------------- _pywebview_ is largely an one-man project, which gets updated sporadically whenever time permits. Any help is appreciated and the best way to contribute is submitting a pull request. Bug fixes are always welcomed. If you wish to submit a new feature, please create an issue and discuss it beforehand. Check out the [contributing guide](https://pywebview.flowrl.com/contributing) to get started. If you find _pywebview_ useful and would like to see it developed in the future, considering sponsoring it. If you represent a company, consider becoming a sponsor to get exposure for your company and connect with Python developers. [![Sponsor on Github](https://pywebview.flowrl.com/github_sponsor_button.png)](https://github.com/sponsors/r0x0r) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # Application architecture | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/architecture.html#main-content) Application architecture ======================== 7/7/19Less than 1 minute * * * [Application architecture](https://pywebview.flowrl.com/guide/architecture.html#application-architecture) ========================================================================================================== There are several way to build your application using _pywebview_: [Pure web server](https://pywebview.flowrl.com/guide/architecture.html#pure-web-server) ---------------------------------------------------------------------------------------- * The most simple case is pointing to a url. This requires a running web server either remotely or locally webview.create_window('Simple browser', 'https://pywebview.flowrl.com') webview.start() If you point to a local web server, you can start an external HTTP server in a background thread manually and or giving a WSGIRef server instance to the url parameter. server = Flask(__name__, static_folder='.', template_folder='.') webview.create_window('My first pywebview application', server) webview.start() See a complete example [Flask-based application](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) When using a local web server, you should protect your API calls against CSRF attacks. See [security](https://pywebview.flowrl.com/guide/security) for more information. While the `file://` protocol is possible, its use is discouraged as it comes with a number of inherit limitations and is not well supported. [JS API with internal HTTP server](https://pywebview.flowrl.com/guide/architecture.html#js-api-with-internal-http-server) -------------------------------------------------------------------------------------------------------------------------- Another approach is using JS API bridge and serving static content with a built-in HTTP server. JS API bridge allows communication between Python and Javascript domains without a web server. The bridge can be created either with `create_window(..., js_api=Api())` or `window.expose` function. To serve static contents, set entrypoint url to a local relative path. This will start a built-in HTTP server automatically. For more details on communication between Python and Javascript refer to [interdomain communication](https://pywebview.flowrl.com/guide/interdomain) . See an example [serverless application](https://github.com/r0x0r/pywebview/tree/master/examples/todos) for a complete implementation. [Serverless](https://pywebview.flowrl.com/guide/architecture.html#serverless) ------------------------------------------------------------------------------ By loading HTML using `webview.create_window(...html='')` or `window.load_html` you can avoid using a web server altogether. This approach has limitations however, as the file system does not exist in the context of the loaded page. Images and other assets can be loaded only inline using Base64. --- # Security | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/security.html#main-content) Security ======== 10/19/18Less than 1 minute * * * [Security](https://pywebview.flowrl.com/guide/security.html#security) ====================================================================== It is advisable to enable SSL for local HTTP server. To accomplish this, simply start the application with the `ssl` paramater set to True `webview.start(ssl=True)`. You need to have `cryptography` pip dependency installed in order to use `ssl`. It is not installed by default. If you employ a REST API, [CSRF attacks](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) can be a major concern. _pywebview_ mitigates this risk by generating a session-unique token that is accessible in Python as `webview.token` and in JavaScript as `window.pywebview.token`. For more information on securing APIs, refer to the [CSRF Prevention Cheat Sheet](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet) . You can also see a practical example in the [Flask app](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) . --- # Freezing | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/freezing.html#main-content) Freezing ======== 10/19/18About 1 min * * * [Freezing](https://pywebview.flowrl.com/guide/freezing.html#freezing) ====================================================================== [Android](https://pywebview.flowrl.com/guide/freezing.html#android) -------------------------------------------------------------------- pywebview is designed to be built with [buildozer](https://buildozer.readthedocs.io/en/latest/) . You need to include following lines in your `buildozer.spec` to bundle pywebview correctly requirements = python3,kivy,pywebview android.add_jars = `pywebview-android.jar` is shipped with `pywebview` and can be found under `site-packages/pywebview/lib`. To get its full path type from webview import util print(util.android_jar_path()) You can see a sample `bulldozer.spec` [here](https://github.com/r0x0r/pywebview/blob/a2b8d0449b206db75f9f364639b85db6eac7f07e/examples/todos/buildozer.spec) [macOS](https://pywebview.flowrl.com/guide/freezing.html#macos) ---------------------------------------------------------------- Use [py2app](https://py2app.readthedocs.io/en/latest/) . For a reference setup.py for py2app, look [here](https://github.com/r0x0r/pywebview/blob/master/examples/py2app_setup.py) . [Windows / Linux](https://pywebview.flowrl.com/guide/freezing.html#windows-linux) ---------------------------------------------------------------------------------- Use [pyinstaller](https://www.pyinstaller.org/) . Pyinstaller picks all the dependencies found in `pywebview`, even if you don't use them. So for example if you have `PyQt` installed, but use `EdgeChromium` renderer on Windows, pyinstaller will bundle `PyQT` all the same. To prevent that you might want to add unwanted dependencies to `excludes` in your spec file. Basic pyinstaller script to package an application which uses index.html as content pyinstaller main.py --add-data index.html:. For one file build pyinstaller main.py --add-data index.html:. --onefile > \[!warning\] In Linux if you get a `cannot find python3.xx.so error` you must add it to the pyinstaller binary list for the application to work (replace 'x' with python version) > > pyinstaller main.py --add-data index.html:. --add-binary /usr/lib/x86_64-linux-gnu/libpython3.x.so:. --onefile In case of using a Javascript library like vue or react you can build the project and use the build directory to the pyinstaller `--add-data`. > \[!warning\] While using _vite_ change the build directory to something else to not conflict with pyinstller's build directory which is also `./dist` Here is a script to build a vue/react app with pyinstaller (assuming output is your new build directory) pyinstaller main.py --add-data output:. Onefile pyinstaller main.py --add-data output:. --onefile [nuitka](http://nuitka.net/) can be used for freezing as well. You may want to use `--nofollow-import-to` to exclude unwanted dependencies. --- # Debugging | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/debugging.html#main-content) Debugging ========= 10/19/18Less than 1 minute * * * [Debugging](https://pywebview.flowrl.com/guide/debugging.html#debugging) ========================================================================= To debug Javascript, set `webview.start(debug=True)`. import webview webview.create_window('Woah dude!', 'https://pywebview.flowrl.com/hello') webview.start(debug=True) This will enable web inspector on macOS, GTK and QT (QTWebEngine only). To open the web inspector on macOS, right click on the page and select Inspect. To disable auto-opening of DevTools, set `webview.settings['OPEN_DEVTOOLS_IN_DEBUG'] = False` before invoking `webview.start()`. Debugging Python code on Android is not possible apart from printing message to `logcat`. Use `adb -s logcat | grep python` for displaying log messages related to Python. Frontend code can be debugged with WebView remote debugging. Refer to [this guide](https://developer.chrome.com/docs/devtools/remote-debugging/webviews/) for details. Remote debugging is supported with the `edgechromium` and `qt` renderers. To take remote debugging into use set `webview.settings['REMOTE_DEBUGGING_PORT']` to the port number you wish to run a debugger on. There is no way to attach an external debugger to MSHTML. The `debug` flag enables Javascript error reporting and right-click context menu. To turn on debug logging for `pywebiew` itself, set `PYWEBVIEW_LOG=debug` environment variable before starting the application. --- # Web engine | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/web_engine.html#main-content) Web engine ========== 10/19/18Less than 1 minute * * * [Web engine](https://pywebview.flowrl.com/guide/web_engine.html#web-engine) ============================================================================ The following renderers are used on each platform | Platform | Code | Renderer | Provider | Browser compatibility | | --- | --- | --- | --- | --- | | Android | | WebKit | | Ever-green Chromium | | GTK | gtk | WebKit | WebKit2 (minimum version >2.2) | | | macOS | | WebKit | WebKit.WKWebView (bundled with OS) | | | QT | qt | WebKit | QtWebEngine / QtWebKit | | | Windows | edgechromium | Chromium | \> .NET Framework 4.6.2 and Edge Runtime installed | Ever-green Chromium | | Windows | cef | CEF | CEF Python | Chrome 66 | | Windows | mshtml | MSHTML | DEPRECATED Internet Explorer MSHTML | IE11 (Windows 10/8/7) | On Windows renderer is chosen in the following order: `edgechromium`, `mshtml`. `mshtml` is the only renderer that is guaranteed to be available on any system. Edge Runtime must be installed in order to use Edge Chromium on Windows. You can download it from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . Distribution guidelines are found [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) . To change a default renderer set either `PYWEBVIEW_GUI` environment variable or pass the rendered value to `webview.start(gui=code)` function parameter. Check for available values in the Code column from the table above. For example to use CEF on Windows export PYWEBVIEW_GUI=cef or import webview webview.start(gui='cef') If you wish to pass custom settings to CEF, refer to [this example](https://pywebview.flowrl.com/examples/cef) To force QT on Linux systems export PYWEBVIEW_GUI=qt or import webview webview.start(gui='qt') [Known issues and limitations](https://pywebview.flowrl.com/guide/web_engine.html#known-issues-and-limitations) ---------------------------------------------------------------------------------------------------------------- [QtWebKit](https://pywebview.flowrl.com/guide/web_engine.html#qtwebkit) ------------------------------------------------------------------------ * Debugging is not supported --- # FAQ | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/faq.html#main-content) FAQ === 10/31/23About 1 min * * * [FAQ](https://pywebview.flowrl.com/guide/faq.html#faq) ======================================================= [How do I set an application icon?](https://pywebview.flowrl.com/guide/faq.html#how-do-i-set-an-application-icon) ------------------------------------------------------------------------------------------------------------------ For macOS, Windows, and Android, the application icon is set via a bundler and embedded in the resulting executable. For GTK and QT, you can set the application icon using `webview.start(icon=icon_path)`, but you might need some additional adjustments to get your icon visible depending on the window manager you use. [Why does _pywebview_ have to run on a main thread?](https://pywebview.flowrl.com/guide/faq.html#why-does-pywebview-have-to-run-on-a-main-thread) -------------------------------------------------------------------------------------------------------------------------------------------------- This is dictated by underlying GUI libraries _pywebview_ is based on. GUI loop is expected to run on a main thread. While some libraries allow the GUI to be run in a sub-thread, Cocoa has a strict requirement regarding the main thread. If you need your logic to run in a main thread, use the `multiprocessing` module. [webview has no attribute create\_window](https://pywebview.flowrl.com/guide/faq.html#webview-has-no-attribute-create-window) ------------------------------------------------------------------------------------------------------------------------------ You probably have a file named `webview.py` in the current directory. Renaming it to something else should fix the problem. [What renderer is used?](https://pywebview.flowrl.com/guide/faq.html#what-renderer-is-used) -------------------------------------------------------------------------------------------- Set `PYWEBVIEW_LOG=debug` environment variable before running your programme. It will display used renderer in the first line of the program output. See available renderers [here](https://pywebview.flowrl.com/guide/renderer) [Terminal window receives key events on macOS](https://pywebview.flowrl.com/guide/faq.html#terminal-window-receives-key-events-on-macos) ----------------------------------------------------------------------------------------------------------------------------------------- If you create a virtual environment using the built-in Python on macOS, a pywebview window will have issues with keyboard focus and Cmd+Tab. The issue can be avoided by using other Python installation. For example to use Python 3 via [Homebrew](https://brew.sh/) . brew install python3 virtualenv pywebview_env -p python3 [Frozen executable is too big](https://pywebview.flowrl.com/guide/faq.html#frozen-executable-is-too-big) --------------------------------------------------------------------------------------------------------- Big executable size is caused by packager picking up unnecessary dependencies. For example if you have `PyQt` installed but use Winforms on Windows, Pyinstaller will bundle both frameworks. To avoid this in Pyinstaller, use `--exclude-module` option to explicitly omit the module. [How do I get a full path of dropped files in `drop` event?](https://pywebview.flowrl.com/guide/faq.html#how-do-i-get-a-full-path-of-dropped-files-in-drop-event) ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Use `DOMEventHandler` and subscribe to the `drop` event. The file path information is stored in `event['dataTransfer']['files'][0]['pywebviewFullPath']` property of the event object. See [this example](https://pywebview.flowrl.com/examples/drag_drop) for details. --- # Javascript–Python bridge | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/interdomain.html#main-content) Javascript–Python bridge ======================== 11/28/19About 2 min * * * [Javascript–Python bridge](https://pywebview.flowrl.com/guide/interdomain.html#javascript%E2%80%93python-bridge) ================================================================================================================= _pywebview_ offers two-way communication between Javascript and Python, enabling interaction between the two languages without a HTTP server. [Shared state](https://pywebview.flowrl.com/guide/interdomain.html#shared-state) --------------------------------------------------------------------------------- `NEW 6.0` Data can be shared via the `Window.state` (Python) and `pywebview.state` (Javascript) objects. Modifying any property on either state object will result in the state being updated on the other side and vice versa. For example, setting `window.state.hello = 'world'` in Python will automatically propagate to `pywebview.state.hello` in Javascript. Only changes on the top level are propagated, ie if you mutate an object, it won't be updated on the other side. State is specific to its window and is preserved between page (re)loads. Binary data can be passed by converting it to Base64 or such. State changes trigger events that can be subscribed to using `pywebview.state += lambda event_type, key, value: pass`. The `event_type` is either `change` or `delete`. The `key` is the property name, and the `value` is the property's value (`None` for delete events). [Run Javascript from Python](https://pywebview.flowrl.com/guide/interdomain.html#run-javascript-from-python) ------------------------------------------------------------------------------------------------------------- `window.evaluate_js(code, callback=None)` allows you to execute arbitrary Javascript code with a last value returned synchronously. If callback function is supplied, then promises are resolved and the callback function is called with the result as a parameter. Javascript types are converted to Python types, eg. JS objects to dicts, arrays to lists, undefined to None. If executed Javascript code results in an error, the error is rethrown as a `webview.util.JavascriptException` in Python. `evaluate_js` wraps Javascript code in a helper wrapper and executes it using `eval`. [See example](https://pywebview.flowrl.com/examples/evaluate_js) `Window.run_js(code)` executes Javascript code as is without any wrapper code. `run_js` does not return a result or handle exceptions. This can be useful in scenarios, where you need to execute Javascript code with the `unsafe-eval` CSP policy set. [Run Python from Javascript](https://pywebview.flowrl.com/guide/interdomain.html#run-python-from-javascript) ------------------------------------------------------------------------------------------------------------- Executing Python functions from Javascript can be done with two different mechanisms. * by exposing an instance of a Python class to the `js_api` parameter of `create_window`. All the callable methods of the class will be exposed to the JS domain as `pywebview.api.method_name` with correct parameter signatures. Method name must not start with an underscore. Nested classes are allowed and are converted into a nested objects in Javascript. Class attributes starting with an underscore are not exposed. Also nested classes that have `_serializable = False` class attribute are ommited. See an [example](https://pywebview.flowrl.com/examples/js_api) . * by passing your function(s) to window object's `expose(func)`. This will expose a function or functions to the JS domain as `pywebview.api.func_name`. Unlike JS API, `expose` allows to expose functions also at the runtime. If there is a name clash between JS API and exposed functions, the latter takes precedence. See an [example](https://pywebview.flowrl.com/examples/expose) . Exposed function returns a promise that is resolved to its result value. Exceptions are rejected and encapsulated inside a Javascript `Error` object. Stacktrace is available via `error.stack`. Exposed functions are executed in separate threads and are not thread-safe. `pywebview.api` is not guaranteed to be available on the `window.onload` event. Subscribe to the `window.pywebviewready` event instead to make sure that `pywebview.api` is ready. [See example](https://pywebview.flowrl.com/examples/js_api) . --- # DOM support | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/dom.html#main-content) DOM support =========== 10/31/23About 2 min * * * [DOM support](https://pywebview.flowrl.com/guide/dom.html#dom-support) ======================================================================= Starting from 5.0 _pywebview_ has got support for basic DOM manipulation, traversal operations and DOM events. See these examples for details [DOM Events](https://pywebview.flowrl.com/examples/dom_events) , [DOM Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) and [DOM Traversal](https://pywebview.flowrl.com/examples/dom_traversal) . [Create element](https://pywebview.flowrl.com/guide/dom.html#create-element) ----------------------------------------------------------------------------- element = window.dom.create_element('
new element
') # insert a new element as body's last child element = window.dom.create_element('

Warning

' parent='#container', mode=ManipulationMode.FirstChild) # insert a new element to #containaer as a first child Manipulation Mode can be one of following `LastChild`, `FirstChild`, `Before`, `After` or `Replace`. `LastChild` is a default value. [Get elements](https://pywebview.flowrl.com/guide/dom.html#get-elements) ------------------------------------------------------------------------- element = window.dom.get_element('#element-id') # returns a first matching Element or None elements = window.dom.get_elements('div') # returns a list of matching Elements [Basic information about element](https://pywebview.flowrl.com/guide/dom.html#basic-information-about-element) --------------------------------------------------------------------------------------------------------------- element.id # return element's id element.classes # return a list like object of element's classes element.style # return a dict like object of element's styles element.tabindex # return element's tab index element.tag # return element's tag name element.text # return element's text content element.value # return input element's value Some element's properties can be set or modified element.id = 'new-id' element.classes.add('green-text') # add .green-text class element.classes.remove('red-background') # remove .red-background class element.classes.toggle('blue-border') # toggle .blue-border class element.style['width'] = '200px' element.tabindex = 108 element.text = 'New content' element.value = 'Luna' [Manupulate element](https://pywebview.flowrl.com/guide/dom.html#manupulate-element) ------------------------------------------------------------------------------------- new_container = window.get_element('#new-container') new_element = element.copy() # copies element as the parent's last child yet_another_element = new_element.copy(new_container, webview.dom.ManipulationMode.FirstChild, "new-id") # copies element to #new-container as a first child yet_another_element = yet_another_element.move('#new-container2') # moves element to #new-container2 as a last child yet_another_element.remove() # remove element new_container.empty() # empty #new-container from its children new_container.append('kick-ass content') # append new DOM to #new-container [Traversal](https://pywebview.flowrl.com/guide/dom.html#traversal) ------------------------------------------------------------------- element.children # return a list of element's children element.next # return a next element in the DOM hierarchy or None element.parent # return element's parent element.previous # return a previous element in the DOM hierarchy or None `body`, `document` and `window` objects can be directly accessed via window.dom.body window.dom.document window.dom.window ### [Element visibility and focus](https://pywebview.flowrl.com/guide/dom.html#element-visibility-and-focus) element.hide() # hide element print(element.visible) # False element.show() # show element print(element.visible) # True element.toggle() # toggle visibility element.focus() # focus element print(element.focused) # True if element can be focused element.blur() # blur element print(element.focused) # False [Events](https://pywebview.flowrl.com/guide/dom.html#events) ------------------------------------------------------------- DOM events can be subscribed directly from Python def print_handler(e): print(e) def shout_handler(e): print('!!!!!!!!') print(e) print('!!!!!!!!') element.on('click', print_handler) element.events.click += shout_handler # these two ways to subscribe to an event are equivalent element.off('click', print_handler) element.events.click -= shout_handler # as well as these two If you need more control over how DOM events are handled, you can use `webview.dom.DOMEventHandler`. It allows setting `preventDefault`, `stopPropagation`, `stopImmediatePropagation` values, as well as debouncing event handlers. window.dom.document.events.dragover += DOMEventHandler(on_drag, prevent_default=True, stop_propagation=True, stop_immediate_propagation=True, debounce=500) _pywebview_ enhances the `drop` event to support full file path information. window.dom.document.events.drop += lambda e: print(e['domTransfer']['files'][0]) # print a full path of the dropped file --- # Usage | pywebview [Skip to main content](https://pywebview.flowrl.com/guide/usage.html#main-content) Usage ===== 10/19/18About 3 min * * * [Usage](https://pywebview.flowrl.com/guide/usage.html#usage) ============================================================= [Basics](https://pywebview.flowrl.com/guide/usage.html#basics) --------------------------------------------------------------- The bare minimum to get _pywebview_ up and running is import webview window = webview.create_window('Woah dude!', 'https://pywebview.flowrl.com') webview.start() The `create_window` function creates a new window and returns a `Window` object instance. Windows created before `webview.start()` are shown as soon as the GUI loop is started. Windows created after the GUI loop is started are shown immediately. You may create as many windows as you wish. All the opened windows are stored as a list in `webview.windows`. The windows are stored in a creation order. To get an instance of currently active (focused) window use `webview.active_window()` import webview def handler(): print(f'There are {len(webview.windows)} windows') print(f'Active window: {webview.active_window().title}') first_window = webview.create_window('pywebview docs', 'https://pywebview.flowrl.com') second_window = webview.create_window('Woah dude!', 'https://woot.fi') second_window.events.shown += handler webview.start() _pywebview_ gives a choice of using several web renderers. To change a web renderer, set the `gui` parameter of the `start` function to the desired value (e.g `cef` or `qt`). See [Web Engine](https://pywebview.flowrl.com/guide/web_engine) for details. [Backend logic](https://pywebview.flowrl.com/guide/usage.html#backend-logic) ----------------------------------------------------------------------------- `webview.start` starts a GUI loop and blocks further code from execution until the last window is destroyed. Since the GUI loop is blocking, you must execute your backend logic in a separate thread or process. You can execute your backend code by passing your function to `webview.start(func, *args)`. This will launch a separate thread and is identical to starting a thread manually. import webview def custom_logic(window): window.toggle_fullscreen() window.evaluate_js('alert("Nice one brother")') window = webview.create_window('Woah dude!', html='

Woah dude!

') webview.start(custom_logic, window) # anything below this line will be executed after program is finished executing pass [Window object](https://pywebview.flowrl.com/guide/usage.html#window-object) ----------------------------------------------------------------------------- The `Window` object provides a number of functions and properties to interact with the window. Here are some of the commonly used methods. * `window.load_url(url)`: Loads a new URL in the window. * `window.load_html(content)`: Loads HTML content directly into the window. * `window.evaluate_js(script)`: Executes JavaScript code in the window and returns the result. * `window.toggle_fullscreen()`: Toggles the window between fullscreen and windowed mode. * `window.resize(width, height)`: Resizes the window to the specified width and height. * `window.move(x, y)`: Moves the window to the specified x and y coordinates. * `window.hide()`: Hides the window. * `window.show()`: Shows the window if it is hidden. * `window.minimize()`: Minimizes the window. * `window.restore()`: Restores the window if it is minimized or maximized. * `window.destroy()`: Closes the window. For a complete list of functions, refer to [API](https://pywebview.flowrl.com/api) [Window events](https://pywebview.flowrl.com/guide/usage.html#window-events) ----------------------------------------------------------------------------- Window object has these window manipulation and navigation events: `closed`, `closing`, `loaded`, `before_load`, `before_show`, `shown`, `minimized`, `maximized`, `restored`, `resized`, `moved`. Window events can be found under the `window.events` container. To subscribe to an event use the `+=` operator and `-=` for unsubscribing. For example: import webview def on_closing(): print("Window is about to close") window = webview.create_window('Woah dude!', 'https://pywebview.flowrl.com') window.events.closing += on_closing webview.start() [Communication between Javascript and Python](https://pywebview.flowrl.com/guide/usage.html#communication-between-javascript-and-python) ----------------------------------------------------------------------------------------------------------------------------------------- You can both run Javascript code from Python and Python code from Javascript. To run Javascript from Python, use `window.evaluate_js(code)`. The function returns result of the last line in the Javascript code. If code returns a promise, you can resolve it by passing a callback function `window.evaluate_js(code, callback)`. If Javascript throws an error, `window.evaluate_js` raises a `webview.errors.JavascriptException`. Alternatively you may use `window.run_js(code)` that executes Javascript code as is. `run_js` does not return a result. To run Python from Javascript, you need to expose your API class with `webview.create_window(url, js_api=api_instance)`. Class member functions will be available in Javascript domain as `window.pywebview.api.funcName`. You can expose single functions with `window.expose(func)` also during the runtime. See [interdomain communication](https://pywebview.flowrl.com/guide/interdomain) for details. import webview class Api(): def log(self, value): print(value) webview.create_window("Test", html="", js_api=Api()) webview.start() Alternatively you may use a more traditional approach with REST API paired with a WSGI server for interdomain communication. See [Flask app](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) for an example. [HTTP server](https://pywebview.flowrl.com/guide/usage.html#http-server) ------------------------------------------------------------------------- _pywebview_ uses internally [bottle.py](https://bottlepy.org/) HTTP server for serving static files. HTTP server is launched automatically for relative local paths. The entrypoint directory serves as a HTTP server root with everything under the directory and its directories shared. You may want to enable SSL for the server by setting `webview.start(ssl=True)`. import webview webview.create_window('Woah dude!', 'src/index.html') webview.start(ssl=True) If you wish to use an external WSGI compatible HTTP server, you can pass a server application object as an URL. from flask import Flask import webview server = Flask(__name__, static_folder='./assets', template_folder='./templates') @server.route("/") def hello_world(): return "Hello, World!" if __name__ == '__main__': webview.create_window('Flask example', server) webview.start() If your intent is to serve files without an HTTP server using the `file://` protocol, you can achieve this by either using an absolute file path or by prefixing the path with the `file://` protocol. This approach is not recommended as it makes the program harder to distribute and has limitations on how it is handled by a web renderer. import webview # this will be served as file:///home/pywebview/project/index.html webview.create_window('Woah dude!', '/home/pywebview/project/index.html') webview.start() ### [DOM support](https://pywebview.flowrl.com/guide/usage.html#dom-support) _pywebview_ has got support for basic DOM manipulation, traversal operations and DOM events. See these examples for details [DOM Events](https://pywebview.flowrl.com/examples/dom_events) , [DOM Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation) and [DOM Traversal](https://pywebview.flowrl.com/examples/dom_traversal) . --- # pywebview (v2.4) Thanks for considering contributing to pywebview. Pywebview is a small-time project, which gets updated sporadically whenever time permits. Any help is more than appreciated and the best way to contribute is submitting a pull request. Bug fixes are always welcome. If you wish to submit a new feature, please create an issue and discuss it beforehand. If you found a bug and want to report it, please test it first in a web-browser that is used by default for your operating system to see if the problem is with your code, rather than pywebview. Do not forget to specify on which platform and pywebview version it occurs. To support pywebview financially, consider becoming a patron of the project. Pywebview has no corporate backing and financial help is welcomed to keep the project alive. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) For other ways to donate refer to the [donation](https://pywebview.flowrl.com/2.4/contributing/donating) page. [Help us improve this page!](https://github.com/r0x0r/pywebview/edit/docs/docs/contributing/README.md) --- # pywebview Thanks for considering contributing to pywebview. Pywebview is a small-time project, which gets updated sporadically whenever time permits. Any help is more than appreciated and the best way to contribute is submitting a pull request. Bug fixes are always welcome. If you wish to submit a new feature, please create an issue and discuss it beforehand. If you found a bug and want to report it, please test it first in a web-browser that is used by default for your operating system to see if the problem is with your code, rather than pywebview. Do not forget to specify on which platform and pywebview version it occurs. To support pywebview financially, consider becoming a patron of the project. Pywebview has no corporate backing and financial help is welcomed to keep the project alive. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) For other ways to donate refer to the [donation](https://pywebview.flowrl.com/3.7/contributing/donating) page. --- # Installation | pywebview (v2.4) [#](https://pywebview.flowrl.com/2.4/guide/installation.html#installation) Installation ======================================================================================== pip install pywebview This will install _pywebview_ with default dependencies. To install _pywebview_ with PyQt5 (available on Linux and macOS) use pip install pywebview[qt] To install _pywebview_ with CEF (available on Windows) use pip install pywebview[cef] [#](https://pywebview.flowrl.com/2.4/guide/installation.html#dependencies) Dependencies ---------------------------------------------------------------------------------------- ### [#](https://pywebview.flowrl.com/2.4/guide/installation.html#windows) Windows [pythonnet](https://github.com/pythonnet/pythonnet) `pythonnet` requires to have .NET 4.0 installed [cefpython](https://github.com/cztomczak/cefpython/) pip install cefpython3 ### [#](https://pywebview.flowrl.com/2.4/guide/installation.html#macos) macOS [pyobjc](https://pythonhosted.org/pyobjc/) `PyObjC` comes presintalled with the Python bundled in macOS. For a stand-alone Python installation you have to install it separately. You can also use QT5 in macOS ### [#](https://pywebview.flowrl.com/2.4/guide/installation.html#linux) Linux You have to install Linux dependencies manually. You can choose between GTK and QT. [PyGObject](https://pygobject.readthedocs.io/en/latest/) is used with GTK. To install dependencies on Ubuntu for both Python 3 and 2 sudo apt install python-gi python-gi-cairo python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-webkit2-4.0 For other distributions, consult the [PyGObject documentation](https://pygobject.readthedocs.io/en/latest/getting_started.html) [PyQt5](http://pyqt.sourceforge.net/Docs/PyQt5/index.html) is used with QT. `pywebview` supports both QtWebChannel (newer and preferred) and QtWebKit implementations. Use QtWebChannel, unless it is not available on your system. To install QtWebChannel on Debian-based systems. sudo apt install python3-pyqt5 python3-pyqt5.qtwebengine python3-pyqt5.qtwebchannel python-pyqt5 python-pyqt5.qtwebengine python-pyqt5.qtwebchannel libqt5webkit5-dev To install QtWebKit. sudo apt install python3-pyqt5 python3-pyqt5.qtwebkit python-pyqt5 python-pyqt5.qtwebkit libqt5webkit5-dev [Help us improve this page!](https://github.com/r0x0r/pywebview/edit/docs/docs/guide/installation.md) [Usage](https://pywebview.flowrl.com/2.4/guide/usage) → --- # About | pywebview (v2.4) [#](https://pywebview.flowrl.com/2.4/guide/#about) About ========================================================= _pywebview_ is a lightweight cross-platform wrapper around a webview component that allows to display HTML content in its own native GUI window. It gives you power of web technologies in your desktop application, hiding the fact that GUI is browser based. You can use pywebview either with a lightweight web framework like [Flask](http://flask.pocoo.org/) or [Bottle](http://bottlepy.org/docs/dev/index.html) or on its own with a two way bridge between Python and DOM. _pywebview_ uses native GUI for creating a web component window: WinForms on Windows, Cocoa on macOS and QT or GTK on Linux. If you choose to freeze your application, pywebview does not bundle a heavy GUI toolkit or web renderer with it keeping the executable size small. _pywebview_ is compatible with both Python 2 and 3. _pywebview_ is a BSD licensed open source project. It is an independent project with no corporate backing. If you find _pywebview_ useful, consider supporting it. More donation options are outlined on the [Donating](https://pywebview.flowrl.com/2.4/contributing/donating) page. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) _pywebview_ is created by [Roman Sirokov](https://github.com/r0x0r/) . Maintained by Roman and [Shiva Prasad](https://github.com/shivaprsdv) . [Help us improve this page!](https://github.com/r0x0r/pywebview/edit/docs/docs/guide/README.md) --- # About | pywebview [#](https://pywebview.flowrl.com/3.7/guide/#about) About ========================================================= _pywebview_ is a lightweight cross-platform wrapper around a webview component that allows to display HTML content in its own native GUI window. You may think of as Electron for Python (minus huge executable sizes). It gives you power of web technologies in your desktop application, hiding the fact that GUI is browser based. You can use pywebview either with a lightweight web framework like [Flask (opens new window)](http://flask.pocoo.org/) or [Bottle (opens new window)](http://bottlepy.org/docs/dev/index.html) or on its own with a two way bridge between Python and DOM. _pywebview_ uses native GUI for creating a web component window: WinForms on Windows, Cocoa on macOS and QT or GTK on Linux. If you choose to freeze your application, pywebview does not bundle a heavy GUI toolkit or web renderer with it keeping the executable size small. _pywebview_ is a BSD licensed open source project. It is an independent project with no corporate backing. If you find _pywebview_ useful, consider supporting it. More donation options are outlined on the [Donating](https://pywebview.flowrl.com/3.7/contributing/donating) page. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) _pywebview_ is created by [Roman Sirokov (opens new window)](https://github.com/r0x0r/) . --- # Installation | pywebview [#](https://pywebview.flowrl.com/3.7/guide/installation.html#installation) Installation ======================================================================================== pip install pywebview This will install _pywebview_ with default dependencies. To install _pywebview_ with PySide2 (available on Linux and macOS and Windows) use pip install pywebview[qt] To install _pywebview_ with CEF (available on Windows) use pip install pywebview[cef] [#](https://pywebview.flowrl.com/3.7/guide/installation.html#dependencies) Dependencies ---------------------------------------------------------------------------------------- ### [#](https://pywebview.flowrl.com/3.7/guide/installation.html#windows) Windows [pythonnet (opens new window)](https://github.com/pythonnet/pythonnet) (requires > .NET 4.0) To use with the latest Chromium you need [WebView2 Runtime (opens new window)](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . If you plan to distribute your software, check out [distribution guidelines (opens new window)](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) too. To use with CEF you need [cefpython (opens new window)](https://github.com/cztomczak/cefpython/) pip install cefpython3 ### [#](https://pywebview.flowrl.com/3.7/guide/installation.html#macos) macOS [pyobjc (opens new window)](https://pythonhosted.org/pyobjc/) `PyObjC` comes presintalled with the Python bundled in macOS. For a stand-alone Python installation you have to install it separately. You can also use QT5 in macOS ### [#](https://pywebview.flowrl.com/3.7/guide/installation.html#linux) Linux `pip install pywebview[qt]` should take of QT dependencies. If it does not work or you would like to use GTK, you may try these recipes. [PyGObject (opens new window)](https://pygobject.readthedocs.io/en/latest/) is used with GTK. To install dependencies on Ubuntu for both Python 3 and 2 sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-webkit2-4.0 For other distributions, consult the [PyGObject documentation (opens new window)](https://pygobject.readthedocs.io/en/latest/getting_started.html) Note that WebKit2 version 2.22 or greater is required for certain features to work correctly. If your distribution ships with an older version, you may need to install it manually from a backport. [PySide2 (opens new window)](https://doc.qt.io/qtforpython-5/) is used with QT. `pywebview` supports both QtWebChannel (newer and preferred) and QtWebKit implementations. Use QtWebChannel, unless it is not available on your system. To install QT via pip pip install qtpy pyside2 To install QtWebChannel on Debian-based systems (more modern, preferred) sudo apt install python3-pyqt5 python3-pyqt5.qtwebengine python3-pyqt5.qtwebchannel libqt5webkit5-dev To install QtWebKit (legacy, but available for more platforms). sudo apt install python3-pyqt5 python3-pyqt5.qtwebkit python-pyqt5 python-pyqt5.qtwebkit libqt5webkit5-dev WARNING Starting from Ubuntu Disco Dingo _pywebview_ can be installed via `apt` on Debian based system as `python-pywebview`. This package features an old version of _pywebview_ that is API incompatible with the current version. If you choose to install it, you can find documentation [here](https://pywebview.flowrl.com/2.4) [Usage](https://pywebview.flowrl.com/3.7/guide/usage) → --- # Multiple Windows | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/multiple_windows#main-content) Multiple Windows ================ 10/15/17Less than 1 minute * * * [Multiple Windows](https://pywebview.flowrl.com/examples/multiple_windows#multiple-windows) ============================================================================================ Create multiple windows. import webview def third_window(): # Create a new window after the loop started webview.create_window('Window #3', html='

Third Window

') if __name__ == '__main__': # Master window master_window = webview.create_window('Window #1', html='

First window

') second_window = webview.create_window('Window #2', html='

Second window

') webview.start(third_window) --- # Drag Drop | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/drag_drop#main-content) Drag Drop ========= Less than 1 minute * * * [Drag Drop](https://pywebview.flowrl.com/examples/drag_drop#drag-drop) ======================================================================= This example demonstrates how to expose Python functions to the Javascript domain. import webview from webview.dom import DOMEventHandler def on_drag(e): pass def on_drop(e): files = e['dataTransfer']['files'] if len(files) == 0: return print(f'Event: {e["type"]}. Dropped files:') for file in files: print(file.get('pywebviewFullPath')) def bind(window): window.dom.document.events.dragenter += DOMEventHandler(on_drag, True, True) window.dom.document.events.dragstart += DOMEventHandler(on_drag, True, True) window.dom.document.events.dragover += DOMEventHandler(on_drag, True, True, debounce=500) window.dom.document.events.drop += DOMEventHandler(on_drop, True, True) if __name__ == '__main__': window = webview.create_window( 'Drag & drop example', html="""

Drag files here

""", ) webview.start(bind, window) --- # Screens | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/screens#main-content) Screens ======= 3/16/21Less than 1 minute * * * [Screens](https://pywebview.flowrl.com/examples/screens#screens) ================================================================= Get available display information using `webview.screens` import webview if __name__ == '__main__': screens = webview.screens print('Available screens:') for i, screen in enumerate(screens): print(f'\nScreen {i + 1}:') print(f' Position: ({screen.x}, {screen.y})') print(f' Size: {screen.width}x{screen.height}') print(f' Scale: {screen.scale}x') print(f' DPI: {screen.dpi}') print(f' Physical Size: {screen.physical_width}x{screen.physical_height}') webview.create_window('', html=f'placed on the monitor {i + 1}', screen=screen) webview.start() --- # Downloads | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/downloads#main-content) Downloads ========= Less than 1 minute * * * [Downloads](https://pywebview.flowrl.com/examples/downloads#downloads) ======================================================================= Enable file downloads import webview if __name__ == '__main__': # Create a standard webview window webview.settings['ALLOW_DOWNLOADS'] = True window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/download') webview.start() --- # Dom Manipulation | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/dom_manipulation#main-content) Dom Manipulation ================ About 1 min * * * [Dom Manipulation](https://pywebview.flowrl.com/examples/dom_manipulation#dom-manipulation) ============================================================================================ This example demonstrates how to manipulate DOM in Python. import random import webview rectangles = [] def random_color(): red = random.randint(0, 255) green = random.randint(0, 255) blue = random.randint(0, 255) return f'rgb({red}, {green}, {blue})' def bind(window): def toggle_disabled(): disabled = None if len(rectangles) > 0 else True remove_button.attributes = {'disabled': disabled} empty_button.attributes = {'disabled': disabled} move_button.attributes = {'disabled': disabled} def create_rectangle(_): color = random_color() rectangle = window.dom.create_element( f'
', rectangle_container ) rectangles.append(rectangle) toggle_disabled() def remove_rectangle(_): if len(rectangles) > 0: rectangles.pop().remove() toggle_disabled() def move_rectangle(_): if len(rectangle_container.children) > 0: rectangle_container.children[-1].move(circle_container) def empty_container(_): rectangle_container.empty() rectangles.clear() toggle_disabled() def change_color(_): circle.style['background-color'] = random_color() def toggle_class(_): circle.classes.toggle('circle') rectangle_container = window.dom.get_element('#rectangles') circle_container = window.dom.get_element('#circles') circle = window.dom.get_element('#circle') toggle_button = window.dom.get_element('#toggle-button') toggle_class_button = window.dom.get_element('#toggle-class-button') duplicate_button = window.dom.get_element('#duplicate-button') remove_button = window.dom.get_element('#remove-button') move_button = window.dom.get_element('#move-button') empty_button = window.dom.get_element('#empty-button') add_button = window.dom.get_element('#add-button') color_button = window.dom.get_element('#color-button') toggle_button.events.click += lambda e: circle.toggle() duplicate_button.events.click += lambda e: circle.copy() toggle_class_button.events.click += toggle_class remove_button.events.click += remove_rectangle move_button.events.click += move_rectangle empty_button.events.click += empty_container add_button.events.click += create_rectangle color_button.events.click += change_color if __name__ == '__main__': window = webview.create_window( 'DOM Manipulations Example', html="""
""", ) webview.start(bind, window) --- # Open File Dialog | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/open_file_dialog#main-content) Open File Dialog ================ 9/27/15Less than 1 minute * * * [Open File Dialog](https://pywebview.flowrl.com/examples/open_file_dialog#open-file-dialog) ============================================================================================ Create an open file dialog after page content is loaded. import webview def open_file_dialog(window): file_types = ('Image Files (*.bmp;*.jpg;*.gif)', 'All files (*.*)') result = window.create_file_dialog( webview.FileDialog.OPEN, allow_multiple=True, file_types=file_types ) print(result) if __name__ == '__main__': window = webview.create_window('Open file dialog example', 'https://pywebview.flowrl.com/hello') webview.start(open_file_dialog, window) --- # Cookies | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/cookies#main-content) Cookies ======= 1/12/23Less than 1 minute * * * [Cookies](https://pywebview.flowrl.com/examples/cookies#cookies) ================================================================= A cookies and local storage example. import webview def read_cookies(window): cookies = window.get_cookies() for c in cookies: print(c.output()) class Api: def clearCookies(self): window.clear_cookies() if __name__ == '__main__': window = webview.create_window('Cookie example', 'assets/cookies.html', js_api=Api()) # We need to explicitly set a http port to persist cookies between sessions webview.start(read_cookies, window, private_mode=False, http_server=True, http_port=13377) --- # Dom Events | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/dom_events#main-content) Dom Events ========== Less than 1 minute * * * [Dom Events](https://pywebview.flowrl.com/examples/dom_events#dom-events) ========================================================================== This example demonstrates how to expose Python functions to the Javascript domain. import webview from webview.dom import DOMEventHandler window = None def click_handler(e): print(e) def input_handler(e): print(e['target']['value']) def remove_handlers(scroll_event, click_event, input_event): scroll_event -= scroll_handler click_event -= click_handler input_event -= input_handler def scroll_handler(e): scroll_top = window.dom.window.node['scrollY'] print(f'Scroll position {scroll_top}') def link_handler(e): print(f'Link target is {e["target"]["href"]}') def bind(window): window.dom.document.events.scroll += DOMEventHandler(scroll_handler, debounce=100) button = window.dom.get_element('#button') button.events.click += click_handler input = window.dom.get_element('#input') input.events.input += input_handler remove_events = window.dom.get_element('#remove') remove_events.on( 'click', lambda e: remove_handlers( window.dom.document.events.scroll, button.events.click, input.events.input ), ) link = window.dom.get_element('#link') link.events.click += DOMEventHandler(link_handler, prevent_default=True) if __name__ == '__main__': window = webview.create_window( 'DOM Event Example', html="""
Click me
""", ) webview.start(bind, window) --- # Save File Dialog | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/save_file_dialog#main-content) Save File Dialog ================ 11/19/15Less than 1 minute * * * [Save File Dialog](https://pywebview.flowrl.com/examples/save_file_dialog#save-file-dialog) ============================================================================================ Create a save file dialog after a delay. import webview def save_file_dialog(window): import time time.sleep(5) result = window.create_file_dialog( webview.FileDialog.SAVE, directory='/', save_filename='test.file' ) print(result) if __name__ == '__main__': window = webview.create_window('Save file dialog', 'https://pywebview.flowrl.com/hello') webview.start(save_file_dialog, window) --- # Destroy Window | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/destroy_window#main-content) Destroy Window ============== 2/12/16Less than 1 minute * * * [Destroy Window](https://pywebview.flowrl.com/examples/destroy_window#destroy-window) ====================================================================================== Programmatically destroy created window after five seconds. import time import webview def destroy(window): # show the window for a few seconds before destroying it: time.sleep(5) print('Destroying window..') window.destroy() print('Destroyed!') if __name__ == '__main__': window = webview.create_window('Destroy Window Example', 'https://pywebview.flowrl.com/hello') webview.start(destroy, window) print('Window is destroyed') --- # Expose | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/expose#main-content) Expose ====== 11/20/19Less than 1 minute * * * [Expose](https://pywebview.flowrl.com/examples/expose#expose) ============================================================== Exposing Python functions to the Javascript domain. import webview def lol(): print('LOL') def wtf(): print('WTF') def echo(arg1, arg2, arg3): print(arg1) print(arg2) print(arg3) def expose(window): window.expose(echo) # expose a function during the runtime window.evaluate_js('pywebview.api.lol()') window.evaluate_js('pywebview.api.wtf()') window.evaluate_js('pywebview.api.echo(1, 2, 3)') if __name__ == '__main__': window = webview.create_window( 'JS Expose Example', html='

JS API function Expose', ) window.expose(lol, wtf) # expose functions beforehand webview.start(expose, window) --- # Get Current Url | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/get_current_url#main-content) Get Current Url =============== 2/8/17Less than 1 minute * * * [Get Current Url](https://pywebview.flowrl.com/examples/get_current_url#get-current-url) ========================================================================================= Print current URL after page is loaded. import webview def get_current_url(window): print(window.get_current_url()) if __name__ == '__main__': window = webview.create_window('Get current URL', 'https://pywebview.flowrl.com/hello') webview.start(get_current_url, window) --- # Get Elements | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/get_elements#main-content) Get Elements ============ 7/7/19Less than 1 minute * * * [Get Elements](https://pywebview.flowrl.com/examples/get_elements#get-elements) ================================================================================ Get DOM elements using selectors. import webview def get_elements(window): heading = window.dom.get_elements('#heading') content = window.dom.get_elements('.content') print(f'Heading:\n {heading[0].node["outerHTML"]}') print(f'Content 1:\n {content[0].node["outerHTML"]}') print(f'Content 2:\n {content[1].node["outerHTML"]}') if __name__ == '__main__': html = """

Heading

Content 1
Content 2
""" window = webview.create_window('Get elements example', html=html) webview.start(get_elements, window) --- # Window State | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/window_state#main-content) Window State ============ Less than 1 minute * * * [Window State](https://pywebview.flowrl.com/examples/window_state#window-state) ================================================================================ Minimize, restore and maximize window programmatically from time import sleep import webview def minimize(window): print('Window is started minimized') sleep(5) print('Restoring window') window.restore() sleep(5) print('Maximizing window') window.maximize() sleep(5) print('Minimizing window') window.minimize() if __name__ == '__main__': window = webview.create_window( 'Minimize window example', html='

Minimize window

', minimized=True ) webview.start(minimize, window) --- # Change Url | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/change_url#main-content) Change Url ========== 11/20/14Less than 1 minute * * * [Change Url](https://pywebview.flowrl.com/examples/change_url#change-url) ========================================================================== Change URL ten seconds after the first URL is loaded. import time import webview def change_url(window): # wait a few seconds before changing url: time.sleep(10) # change url: window.load_url('https://pywebview.flowrl.com/hello') if __name__ == '__main__': window = webview.create_window('URL Change Example', 'http://www.google.com') webview.start(change_url, window) --- # Run Js | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/run_js#main-content) Run Js ====== Less than 1 minute * * * [Run Js](https://pywebview.flowrl.com/examples/run_js#run-js) ============================================================== Run Javascript code from Python. import webview def run_js(window): result = window.run_js( r""" var h1 = document.createElement('h1') var text = document.createTextNode('Hello pywebview') h1.appendChild(text) document.body.appendChild(h1) function test() { return 420 } test() """ ) print(result) if __name__ == '__main__': window = webview.create_window('Run JavaScript', html='') webview.start(run_js, window) --- # Toggle Fullscreen | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/toggle_fullscreen#main-content) Toggle Fullscreen ================= 2/7/17Less than 1 minute * * * [Toggle Fullscreen](https://pywebview.flowrl.com/examples/toggle_fullscreen#toggle-fullscreen) =============================================================================================== Switch application window to a full-screen mode after five seconds.. import time import webview def toggle_fullscreen(window): # wait a few seconds before toggle fullscreen: time.sleep(5) window.toggle_fullscreen() if __name__ == '__main__': window = webview.create_window('Full-screen window', 'https://pywebview.flowrl.com/hello') webview.start(toggle_fullscreen, window) --- # Move Window | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/move_window#main-content) Move Window =========== 10/18/19Less than 1 minute * * * [Move Window](https://pywebview.flowrl.com/examples/move_window#move-window) ============================================================================= Set window coordinates and move window after its creation. from time import sleep import webview def move(window): print(f'Window coordinates are ({window.x}, {window.y})') print(f'Window dimensions are ({window.width}x{window.height})') # Get the primary screen to calculate relative position screens = webview.screens if screens: primary_screen = screens[0] print(f'Primary screen: {primary_screen.width}x{primary_screen.height}') # Move to bottom-right area of screen (with some padding) new_x = primary_screen.width - window.width - 100 new_y = primary_screen.height - window.height - 100 else: # Fallback to absolute coordinates new_x, new_y = 500, 500 sleep(2) window.move(new_x, new_y) print(f'Moving window to ({new_x}, {new_y})...') sleep(1) print(f'Window coordinates are now ({window.x}, {window.y})') if __name__ == '__main__': window = webview.create_window('Move window example', html='

Move window

', x=300, y=300) webview.start(move, window) --- # Window Title Change | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/window_title_change#main-content) Window Title Change =================== 1/26/18Less than 1 minute * * * [Window Title Change](https://pywebview.flowrl.com/examples/window_title_change#window-title-change) ===================================================================================================== Change window title every three seconds. import webview def change_title(window): """changes title every 3 seconds""" for i in range(1, 100): # exit loop when window is closed if window.events.closed.wait(3): break window.title = f'New Title #{i}' print(window.title) if __name__ == '__main__': window = webview.create_window('Change title example', 'https://pywebview.flowrl.com/hello') webview.start(change_title, window) --- # Confirm Close | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/confirm_close#main-content) Confirm Close ============= Less than 1 minute * * * [Confirm Close](https://pywebview.flowrl.com/examples/confirm_close#confirm-close) =================================================================================== A window with a quit confirmation dialog. import webview if __name__ == '__main__': # Create a standard webview window webview.create_window( 'Confirm Quit Example', 'https://pywebview.flowrl.com/hello', confirm_close=True ) webview.start() --- # Cef | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/cef#main-content) Cef === 2/12/19Less than 1 minute * * * [Cef](https://pywebview.flowrl.com/examples/cef#cef) ===================================================== Create a CEF window with custom Chrome settings. Available only on Windows. import webview # To pass custom settings to CEF, import and update settings dict from webview.platforms.cef import browser_settings, settings settings.update({'persist_session_cookies': True}) browser_settings.update({'dom_paste_disabled': False}) if __name__ == '__main__': webview.create_window('CEF browser', 'https://pywebview.flowrl.com/hello') webview.start(gui='cef') --- # Events | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/events#main-content) Events ====== 7/7/19Less than 1 minute * * * [Events](https://pywebview.flowrl.com/examples/events#events) ============================================================== Subscribe and unsubscribe to pywebview events. import webview def on_before_show(window): print('Native window object', window.native) def on_closed(): print('pywebview window is closed') def on_closing(): print('pywebview window is closing') def on_initialized(renderer): # return False to cancel initialization print(f'GUI is initialized with renderer: {renderer}') def on_shown(): print('pywebview window shown') def on_minimized(): print('pywebview window minimized') def on_restored(): print('pywebview window restored') def on_maximized(): print('pywebview window maximized') def on_resized(width, height): print(f'pywebview window is resized. new dimensions are {width} x {height}') # you can supply optional window argument to access the window object event was triggered on def on_loaded(window): print('DOM is ready') # unsubscribe event listener window.events.loaded -= on_loaded window.load_url('https://pywebview.flowrl.com/hello') def on_moved(x, y): print(f'pywebview window is moved. new coordinates are x: {x}, y: {y}') if __name__ == '__main__': window = webview.create_window( 'Simple browser', 'https://pywebview.flowrl.com/', confirm_close=True ) window.events.closed += on_closed window.events.closing += on_closing window.events.before_show += on_before_show window.events.initialized += on_initialized window.events.shown += on_shown window.events.loaded += on_loaded window.events.minimized += on_minimized window.events.maximized += on_maximized window.events.restored += on_restored window.events.resized += on_resized window.events.moved += on_moved webview.start() --- # Confirmation Dialog | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/confirmation_dialog#main-content) Confirmation Dialog =================== 11/14/22Less than 1 minute * * * [Confirmation Dialog](https://pywebview.flowrl.com/examples/confirmation_dialog#confirmation-dialog) ===================================================================================================== A window with a confirmation dialog. import webview def open_confirmation_dialog(window): result = window.create_confirmation_dialog('Question', 'Are you ok with this?') if result: print('User clicked OK') else: print('User clicked Cancel') if __name__ == '__main__': window = webview.create_window( 'Confirmation dialog example', 'https://pywebview.flowrl.com/hello' ) webview.start(open_confirmation_dialog, window) --- # Debug | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/debug#main-content) Debug ===== 10/19/18Less than 1 minute * * * [Debug](https://pywebview.flowrl.com/examples/debug#debug) =========================================================== A debug window example that opens DevTools. import webview if __name__ == '__main__': webview.create_window('Debug window', 'https://pywebview.flowrl.com/hello') webview.start(debug=True) --- # Focus | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/focus#main-content) Focus ===== 3/30/23Less than 1 minute * * * [Focus](https://pywebview.flowrl.com/examples/focus#focus) =========================================================== Create a non-focusable window that can be useful for onscreen floating tools. import webview if __name__ == '__main__': webview.create_window( 'Nonfocusable window', html='

You shouldnt be able to type into this window...

...but still you can click elements in this window...

', focus=False, ) webview.start() --- # Frameless | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/frameless#main-content) Frameless ========= 2/16/19Less than 1 minute * * * [Frameless](https://pywebview.flowrl.com/examples/frameless#frameless) ======================================================================= Create a frameless window. The window can be moved around by dragging any point. import webview if __name__ == '__main__': # Create a resizable webview window with minimum size constraints webview.create_window( 'Frameless window', 'http://pywebview.flowrl.com/hello', frameless=True, easy_drag=True ) webview.start() --- # Fullscreen | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/fullscreen#main-content) Fullscreen ========== 11/29/15Less than 1 minute * * * [Fullscreen](https://pywebview.flowrl.com/examples/fullscreen#fullscreen) ========================================================================== Create a fullscreen window. import webview if __name__ == '__main__': # Create a non-resizable webview window with 800x600 dimensions webview.create_window( 'Full-screen window', 'https://pywebview.flowrl.com/hello', fullscreen=True ) webview.start() --- # Http Server | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/http_server#main-content) Http Server =========== Less than 1 minute * * * [Http Server](https://pywebview.flowrl.com/examples/http_server#http-server) ============================================================================= A built-in HTTP server example. import webview if __name__ == '__main__': webview.create_window('My first HTML5 application', 'assets/index.html') # HTTP server is started automatically for local relative paths webview.start(ssl=True) --- # Icon | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/icon#main-content) Icon ==== Less than 1 minute * * * [Icon](https://pywebview.flowrl.com/examples/icon#icon) ======================================================== Set window icon using \`webview.start(icon=). This is supported only on GTK and QT. For other platforms, icon is set during freezing. import webview if __name__ == '__main__': window = webview.create_window('Set window icon', 'https://pywebview.flowrl.com/hello') webview.start(icon='../assets/logo.png') --- # Load Css | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/load_css#main-content) Load Css ======== Less than 1 minute * * * [Load Css](https://pywebview.flowrl.com/examples/load_css#load-css) ==================================================================== Loading custom CSS in a webview window import webview def load_css(window): window.load_css('body { background: red !important; }') if __name__ == '__main__': window = webview.create_window('Load CSS Example', 'https://pywebview.flowrl.com/hello') webview.start(load_css, window) --- # Load Html | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/load_html#main-content) Load Html ========= Less than 1 minute * * * [Load Html](https://pywebview.flowrl.com/examples/load_html#load-html) ======================================================================= Loading new HTML after the window is created from time import sleep import webview def load_html(window): sleep(5) window.load_html('

This is dynamically loaded HTML

') if __name__ == '__main__': window = webview.create_window('Load HTML Example', html='

This is initial HTML

') webview.start(load_html, window) --- # Localhost Ssl | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/localhost_ssl#main-content) Localhost Ssl ============= Less than 1 minute * * * [Localhost Ssl](https://pywebview.flowrl.com/examples/localhost_ssl#localhost-ssl) =================================================================================== Use SSL with a local HTTP server. import webview if __name__ == '__main__': webview.create_window('Local SSL Test', 'assets/index.html') webview.start(ssl=True) --- # On Top | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/on_top#main-content) On Top ====== 3/26/20Less than 1 minute * * * [On Top](https://pywebview.flowrl.com/examples/on_top#on-top) ============================================================== Create a window that stays on top of other windows. import time import webview def deactivate(window): # window starts as on top of and reverts back to normal after 20 seconds time.sleep(20) window.on_top = False window.load_html('

This window is no longer on top of other windows

') if __name__ == '__main__': # Create webview window that stays on top of, all other windows window = webview.create_window( 'Topmost window', html='

This window is on top of other windows

', on_top=True ) webview.start(deactivate, window) --- # Settings | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/settings#main-content) Settings ======== Less than 1 minute * * * [Settings](https://pywebview.flowrl.com/examples/settings#settings) ==================================================================== Use application flags to modify default behaviour of pywebview import webview html = """

target='_blank' link will be opened in the current window.

""" if __name__ == '__main__': print(webview.settings) webview.settings['OPEN_EXTERNAL_LINKS_IN_BROWSER'] = False webview.settings['OPEN_DEVTOOLS_IN_DEBUG'] = False window = webview.create_window('Application flags', html=html) webview.start() --- # Hide Window | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/hide_window#main-content) Hide Window =========== 10/27/19Less than 1 minute * * * [Hide Window](https://pywebview.flowrl.com/examples/hide_window#hide-window) ============================================================================= Programmatically hide and show window. import time import webview def hide_show(window): print('Window is started hidden') time.sleep(5) print('Showing window') window.show() time.sleep(5) print('Hiding window') window.hide() time.sleep(5) print('And showing again') window.show() if __name__ == '__main__': window = webview.create_window( 'Hide / show window', 'https://pywebview.flowrl.com/hello', hidden=True ) webview.start(hide_show, window) --- # Evaluate Js Async | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/evaluate_js_async#main-content) Evaluate Js Async ================= Less than 1 minute * * * [Evaluate Js Async](https://pywebview.flowrl.com/examples/evaluate_js_async#evaluate-js-async) =============================================================================================== Run asynchronous Javascript code and invoke a callback. import webview def callback(result): print(result) def evaluate_js_async(window): window.evaluate_js( """ new Promise((resolve, reject) => { setTimeout(() => { resolve('Whaddup!'); }, 300); }); """, callback, ) if __name__ == '__main__': window = webview.create_window('Run async Javascript', html='') webview.start(evaluate_js_async, window) --- # Links | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/links#main-content) Links ===== 7/7/19Less than 1 minute * * * [Links](https://pywebview.flowrl.com/examples/links#links) =========================================================== Demonstrate a difference between different link types import webview html = """

Links

Regular links are opened in the application window.

target='_blank' links are opened in an external browser.

""" if __name__ == '__main__': window = webview.create_window('Link types', html=html) webview.start() --- # Py2app Setup | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/py2app_setup#main-content) Py2app Setup ============ Less than 1 minute * * * [Py2app Setup](https://pywebview.flowrl.com/examples/py2app_setup#py2app-setup) ================================================================================ An example of py2app setup.py script for freezing your pywebview application Usage: `python setup.py py2app` import os from setuptools import setup def tree(src): return [\ (root, map(lambda f: os.path.join(root, f), files))\ for (root, dirs, files) in os.walk(os.path.normpath(src))\ ] ENTRY_POINT = ['simple_browser.py'] DATA_FILES = tree('DATA_FILES_DIR') + tree('DATA_FILE_DIR2') OPTIONS = { 'argv_emulation': False, 'strip': True, #'iconfile': 'icon.icns', # uncomment to include an icon 'includes': ['WebKit', 'Foundation', 'webview'], } setup( app=ENTRY_POINT, data_files=DATA_FILES, options={'py2app': OPTIONS}, setup_requires=['py2app'], ) --- # Pystray Icon | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/pystray_icon#main-content) Pystray Icon ============ Less than 1 minute * * * [Pystray Icon](https://pywebview.flowrl.com/examples/pystray_icon#pystray-icon) ================================================================================ Run pywebview alongside with pystray to display a system tray icon. import multiprocessing import sys from PIL import Image from pystray import Icon, Menu, MenuItem import webview if sys.platform == 'darwin': ctx = multiprocessing.get_context('spawn') Process = ctx.Process Queue = ctx.Queue else: Process = multiprocessing.Process Queue = multiprocessing.Queue webview_process = None def run_webview(): webview.create_window('Webview', 'https://pywebview.flowrl.com/hello') webview.start() if __name__ == '__main__': def start_webview_process(): global webview_process webview_process = Process(target=run_webview) webview_process.start() def on_open(icon, item): global webview_process if not webview_process.is_alive(): start_webview_process() def on_exit(icon, item): icon.stop() start_webview_process() image = Image.open('assets/logo.png') menu = Menu(MenuItem('Open', on_open), MenuItem('Exit', on_exit)) icon = Icon('Pystray', image, menu=menu) icon.run() webview_process.terminate() --- # Qt Test | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/qt_test#main-content) Qt Test ======= Less than 1 minute * * * [Qt Test](https://pywebview.flowrl.com/examples/qt_test#qt-test) ================================================================= Create a pywebview windows using QT (normally GTK is preferred) import webview if __name__ == '__main__': # Create a non-resizable webview window with 800x600 dimensions webview.create_window('Qt Example', 'http://flowrl.com') webview.start(gui='qt') --- # Headers | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/headers#main-content) Headers ======= Less than 1 minute * * * [Headers](https://pywebview.flowrl.com/examples/headers#headers) ================================================================= Subscribe and unsubscribe to pywebview events. from bottle import Bottle, request import webview def on_request(window, request): print('Request sent: ' + request.url) request.headers['pywebview'] = 'header' def on_response(window, response): print('Response received: ' + response.url) app = Bottle() @app.route('/') def display_headers(): headers = dict(request.headers) return '
'.join(f'{key}: {value}' for key, value in headers.items()) if __name__ == '__main__': window = webview.create_window('Headers', app) window.events.request_sent += on_request window.events.response_received += on_response webview.start(debug=True) --- # Resize | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/resize#main-content) Resize ====== Less than 1 minute * * * [Resize](https://pywebview.flowrl.com/examples/resize#resize) ============================================================== Resize window. from time import sleep import webview def resize(window): print(f'Window size is ({window.width}, {window.height})') sleep(2) window.resize(420, 420) print(f'Window size is ({window.width}, {window.height})') if __name__ == '__main__': window = webview.create_window( 'Resize window example', html='

Resize window

', width=800, height=600 ) webview.start(resize, window) --- # Simple Browser | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/simple_browser#main-content) Simple Browser ============== Less than 1 minute * * * [Simple Browser](https://pywebview.flowrl.com/examples/simple_browser#simple-browser) ====================================================================================== The most basic example of creating a webview window. import webview if __name__ == '__main__': # Create a standard webview window window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/hello') webview.start() --- # Min Size | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/min_size#main-content) Min Size ======== 11/18/15Less than 1 minute * * * [Min Size](https://pywebview.flowrl.com/examples/min_size#min-size) ==================================================================== Set minimum window dimensions. import webview if __name__ == '__main__': # Create a resizable webview window with minimum size constraints webview.create_window( 'Minimum window size', 'https://pywebview.flowrl.com/hello', min_size=(400, 200) ) webview.start() --- # User Agent | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/user_agent#main-content) User Agent ========== 4/30/20Less than 1 minute * * * [User Agent](https://pywebview.flowrl.com/examples/user_agent#user-agent) ========================================================================== Change the user-agent of a window. import webview if __name__ == '__main__': webview.create_window('User Agent Test', 'https://pywebview.flowrl.com/hello') webview.start(user_agent='Custom user agent') --- # Vibrancy | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/vibrancy#main-content) Vibrancy ======== 1/12/23Less than 1 minute * * * [Vibrancy](https://pywebview.flowrl.com/examples/vibrancy#vibrancy) ==================================================================== This example demonstrates how to set vibrancy on macOS. import webview def load_css(window): window.load_css('body { background: transparent !important; }') if __name__ == '__main__': window = webview.create_window( 'Vibrancy example', 'https://pywebview.flowrl.com/hello', transparent=True, vibrancy=True ) webview.start(load_css, window) --- # Dom Traversal | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/dom_traversal#main-content) Dom Traversal ============= Less than 1 minute * * * [Dom Traversal](https://pywebview.flowrl.com/examples/dom_traversal#dom-traversal) =================================================================================== This example demonstrates how to traverse DOM in Python. import webview def bind(window): container = window.dom.get_element('#container') container_button = window.dom.get_element('#container-button') blue_rectangle = window.dom.get_element('#blue-rectangle') blue_parent_button = window.dom.get_element('#blue-parent-button') blue_next_button = window.dom.get_element('#blue-next-button') blue_previous_button = window.dom.get_element('#blue-previous-button') container_button.events.click += lambda e: print(container.children) blue_parent_button.events.click += lambda e: print(blue_rectangle.parent) blue_next_button.events.click += lambda e: print(blue_rectangle.next) blue_previous_button.events.click += lambda e: print(blue_rectangle.previous) if __name__ == '__main__': window = webview.create_window( 'DOM Manipulations Example', html="""

Container

RED
BLUE
GREEN
""", ) webview.start(bind, window) --- # Evaluate Js | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/evaluate_js#main-content) Evaluate Js =========== Less than 1 minute * * * [Evaluate Js](https://pywebview.flowrl.com/examples/evaluate_js#evaluate-js) ============================================================================= Run Javascript code from Python. import webview from webview.errors import JavascriptException def evaluate_js(window): result = window.evaluate_js( r""" var h1 = document.createElement('h1') var text = document.createTextNode('Hello pywebview') h1.appendChild(text) document.body.appendChild(h1) document.body.style.backgroundColor = '#212121' document.body.style.color = '#f2f2f2' // Return user agent 'User agent:\n' + navigator.userAgent; """ ) print(result) try: result = window.evaluate_js('syntaxerror#$%#$') except JavascriptException as e: print('Javascript exception occured: ', e) if __name__ == '__main__': window = webview.create_window('Evaluate JavaScript', html='') webview.start(evaluate_js, window) --- # Drag Region | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/drag_region#main-content) Drag Region =========== Less than 1 minute * * * [Drag Region](https://pywebview.flowrl.com/examples/drag_region#drag-region) ============================================================================= Demonstrates the use of dynamic draggable regions in a frameless window using pywebview. import webview html = """
Drag me!

Click the button to add more draggable regions, or drag the orange areas to move the window.

""" if __name__ == '__main__': window = webview.create_window( 'API example', html=html, frameless=True, easy_drag=False, ) webview.start() --- # Loading Animation | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/loading_animation#main-content) Loading Animation ================= 5/17/17About 1 min * * * [Loading Animation](https://pywebview.flowrl.com/examples/loading_animation#loading-animation) =============================================================================================== Create a loading animation that is displayed before application is loaded. import webview html = """
Loading...

Content is loaded!

""" if __name__ == '__main__': window = webview.create_window('Loading Animation', html=html, background_color='#333333') webview.start() --- # Localization | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/localization#main-content) Localization ============ 11/12/16Less than 1 minute * * * [Localization](https://pywebview.flowrl.com/examples/localization#localization) ================================================================================ Localize system text string used by pywebview. For a full list of used string, refer to the `webview/localization.py` file. import webview if __name__ == '__main__': localization = { 'global.saveFile': 'Сохранить файл', 'cocoa.menu.about': 'О программе', 'cocoa.menu.services': 'Cлужбы', 'cocoa.menu.view': 'Вид', 'cocoa.menu.hide': 'Скрыть', 'cocoa.menu.hideOthers': 'Скрыть остальные', 'cocoa.menu.showAll': 'Показать все', 'cocoa.menu.quit': 'Завершить', 'cocoa.menu.fullscreen': 'Перейти ', 'windows.fileFilter.allFiles': 'Все файлы', 'windows.fileFilter.otherFiles': 'Остальлные файльы', 'linux.openFile': 'Открыть файл', 'linux.openFiles': 'Открыть файлы', 'linux.openFolder': 'Открыть папку', } window_localization_override = { 'global.saveFile': 'Save file', } webview.create_window( 'Localization Example', 'https://pywebview.flowrl.com/hello', localization=window_localization_override, ) webview.start(localization=localization) --- # Remote Debugging | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/remote_debugging#main-content) Remote Debugging ================ Less than 1 minute * * * [Remote Debugging](https://pywebview.flowrl.com/examples/remote_debugging#remote-debugging) ============================================================================================ Enable remote debugging when using `edgechromium`. This can be used to write tests for the application using Playwright. See [https://playwright.dev/docs/webview2](https://playwright.dev/docs/webview2) for how to configure it. import webview if __name__ == '__main__': webview.settings['REMOTE_DEBUGGING_PORT'] = 9222 window = webview.create_window('Webview', 'https://pywebview.flowrl.com/hello') webview.start() --- # State | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/state#main-content) State ===== Less than 1 minute * * * [State](https://pywebview.flowrl.com/examples/state#state) =========================================================== Demonstrate usage of the state object to share state between Python and JavaScript. import webview html = """

State

Counter value: 0

""" def on_counter_change(type, key, value): print(f'Event {type} for {key} value : {value}') def decrease_counter(): window.state.counter -= 1 def on_loaded(window): window.expose(decrease_counter) window.state += on_counter_change if __name__ == '__main__': global window window = webview.create_window('State example', html=html) window.state.counter = 0 window.events.loaded += on_loaded webview.start(debug=True) --- # Transparent | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/transparent#main-content) Transparent =========== Less than 1 minute * * * [Transparent](https://pywebview.flowrl.com/examples/transparent#transparent) ============================================================================= Create a transparent frameless window with custom chrome. import webview html = """ Test app
Danger!
Alert!
Lorem ipsum dolor sit amet, consectetur adipiscing elit
""" if __name__ == '__main__': # Create a transparent webview window webview.create_window( 'Transparent window', html=html, transparent=True, frameless=True ) # , hidden=True) webview.start() --- # Js Api | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/js_api#main-content) Js Api ====== 11/7/17About 1 min * * * [Js Api](https://pywebview.flowrl.com/examples/js_api#js-api) ============================================================== Create an application without a HTTP server. The application uses Javascript API object to communicate between Python and Javascript. import random import sys import threading import time import webview html = """

JS API Example

pywebview is not ready






""" class HeavyStuffAPI: def __init__(self): self.cancel_heavy_stuff_flag = False def doHeavyStuff(self): time.sleep(0.1) # sleep to prevent from the ui thread from freezing for a moment now = time.time() self.cancel_heavy_stuff_flag = False for i in range(0, 1000000): _ = i * random.randint(0, 1000) if self.cancel_heavy_stuff_flag: response = {'message': 'Operation cancelled'} break else: then = time.time() response = { 'message': f'Operation took {then - now:.1f} seconds on the thread {threading.current_thread()}' } return response def cancelHeavyStuff(self): time.sleep(0.1) self.cancel_heavy_stuff_flag = True class NotExposedApi: _serializable = False def notExposedMethod(self): return 'This method is not exposed' class Api: heavy_stuff = HeavyStuffAPI() _this_wont_be_exposed = HeavyStuffAPI() this_wont_be_exposed = NotExposedApi() def init(self): response = {'message': f'Hello from Python {sys.version}'} return response def getRandomNumber(self): response = { 'message': f'Here is a random number courtesy of randint: {random.randint(0, 100000000)}' } return response def sayHelloTo(self, name): response = {'message': f'Hello {name}!'} return response def error(self): raise Exception('This is a Python exception') if __name__ == '__main__': api = Api() window = webview.create_window('JS API example', html=html, js_api=api) webview.start() --- # Multiple Servers | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/multiple_servers#main-content) Multiple Servers ================ About 1 min * * * [Multiple Servers](https://pywebview.flowrl.com/examples/multiple_servers#multiple-servers) ============================================================================================ Create multiple windows, some of which have their own servers, both before and after `webview.start()` is called. import bottle import webview # We'll have a global list of our windows so our web app can give us information # about them windows = [] # A simple function to format a description of our servers def serverDescription(server): return f'{str(server).replace("<", "").replace(">", "")}' # Define a couple of simple web apps using Bottle app1 = bottle.Bottle() @app1.route('/') def hello(): return '

Second Window

This one is a web app and has its own server.

' app2 = bottle.Bottle() @app2.route('/') def hello2(): head = """ """ body = f"""

Third Window

This one is another web app and has its own server. It was started after webview.start.

Server Descriptions:

Window Object IP Address
Global Server {serverDescription(webview.http.global_server)} {webview.http.global_server.address if webview.http.global_server is not None else 'None'}
First Window {serverDescription(windows[0]._server)} {windows[0]._server.address if windows[0]._server is not None else 'None'}
Second Window {serverDescription(windows[1]._server)} {windows[1]._server.address}
Third Window {serverDescription(windows[2]._server)} {windows[2]._server.address}
""" return head + body def third_window(): # Create a new window after the loop started windows.append(webview.create_window('Window #3', url=app2)) if __name__ == '__main__': # Master window windows.append( webview.create_window( 'Window #1', html='

First window

This one is static HTML and just uses the global server for api calls.

', ) ) windows.append(webview.create_window('Window #2', url=app1, http_port=3333)) webview.start(third_window, http_server=True, http_port=3334) --- # Multiprocess | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/multiprocess#main-content) Multiprocess ============ About 1 min * * * [Multiprocess](https://pywebview.flowrl.com/examples/multiprocess#multiprocess) ================================================================================ Example of running pywebview in a separate process with shared state. Main thread is not blocked in this example. import multiprocessing import threading import time import webview html = """

Multiprocess State Example

Counter value: 0

Message from main process: Waiting...

Function to run webview in a separate process with shared state.""" def on_counter_change(type, key, value): print(f'Webview process - {key}: {value}') def sync_from_shared_state(): """Sync webview state from shared dictionary.""" try: # Check if shared state has changed and update webview state if window.state.counter != shared_dict.get('counter', 0): window.state.counter = shared_dict['counter'] if window.state.message != shared_dict.get('message', 'Waiting...'): window.state.message = shared_dict['message'] except Exception as e: print(f'Error syncing state: {e}') def on_loaded(window): window.state += on_counter_change # Sync initial state from shared dictionary window.state.counter = shared_dict.get('counter', 0) window.state.message = shared_dict.get('message', 'Waiting...') def periodic_sync(): while True: try: time.sleep(0.5) # Check every 500ms sync_from_shared_state() except Exception: break # Exit if window is closed sync_thread = threading.Thread(target=periodic_sync, daemon=True) sync_thread.start() window = webview.create_window('Multiprocess State Example', html=html) window.state.counter = shared_dict.get('counter', 0) window.state.message = shared_dict.get('message', 'Waiting...') window.events.loaded += on_loaded webview.start() if __name__ == '__main__': # Create shared state between processes manager = multiprocessing.Manager() shared_dict = manager.dict() shared_dict['counter'] = 0 shared_dict['message'] = 'Waiting...' # Create and start the webview process webview_process = multiprocessing.Process(target=run_webview, args=(shared_dict,)) webview_process.start() # Main process is free to do other work print('Webview started in separate process') print('Main process is free to do other work...') # Simulate some work in the main process and update state for i in range(10): time.sleep(2) # Update shared state from main process shared_dict['counter'] = i + 1 shared_dict['message'] = f'Main process step {i+1}/10' print(f"Main process working... {i+1}/10 (counter: {shared_dict['counter']})") shared_dict['message'] = 'Main process completed!' print('Main process finished its work') print('Waiting for webview process to complete...') # Wait for the webview process to finish webview_process.join() print('Webview process completed') --- # Menu | pywebview [Skip to main content](https://pywebview.flowrl.com/examples/menu.html#main-content) Menu ==== 4/23/22Less than 1 minute * * * [Menu](https://pywebview.flowrl.com/examples/menu.html#menu) ============================================================= Create an application menu. import webview from webview.menu import Menu, MenuAction, MenuSeparator def change_active_window_content(): active_window = webview.active_window() if active_window: active_window.load_html('

You changed this window!

') def click_me(): active_window = webview.active_window() if active_window: active_window.load_html('

You clicked me!

') def test(): active_window = webview.active_window() if active_window: active_window.load_html('

This is a test!

') def do_nothing(): pass def say_this_is_window_2(): active_window = webview.active_window() if active_window: active_window.load_html('

This is window 2

') def open_save_file_dialog(): active_window = webview.active_window() active_window.create_file_dialog( webview.FileDialog.SAVE, directory='/', save_filename='test.file' ) def open_preferences(): active_window = webview.active_window() if active_window: active_window.load_html( '

Preferences

App preferences would open here (macOS app menu)

' ) def check_for_updates(): active_window = webview.active_window() if active_window: active_window.load_html( '

Check for Updates

Checking for updates... (macOS app menu)

' ) if __name__ == '__main__': # App menu items (macOS only - appears between About and Services) # On other platforms, this menu is ignored macos_app_menu = Menu( '__app__', [\ MenuAction('Preferences...', open_preferences),\ MenuSeparator(),\ MenuAction('Check for Updates', check_for_updates),\ ], ) window_menu = [Menu('Window', [MenuAction('Test', test)])] app_menu = [\ macos_app_menu, # macOS app menu items\ Menu(\ 'Menu 1',\ [\ MenuAction('Change Active Window Content', change_active_window_content),\ MenuSeparator(),\ Menu(\ 'Random',\ [\ MenuAction('Click Me', click_me),\ MenuAction('File Dialog', open_save_file_dialog),\ ],\ ),\ ],\ ),\ Menu('Menu 2', [MenuAction('This will do nothing', do_nothing)]),\ ] window_1 = webview.create_window( 'Application Menu Example', 'https://pywebview.flowrl.com/hello' ) window_2 = webview.create_window( 'Window Menu Example', html='

Another window to test application menu

', menu=window_menu, ) webview.start(menu=app_menu) --- # Examples | pywebview (v2.4) [#](https://pywebview.flowrl.com/2.4/examples/#examples) Examples ================================================================== Here you can find examples demonstrating different aspects of pywebview. For non-trivial examples on how to create a full-grown application refer to the repository. * [Serverless application](https://github.com/r0x0r/pywebview/tree/master/examples/todos) * [Flask-based application](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) [Help us improve this page!](https://github.com/r0x0r/pywebview/edit/docs/docs/examples/README.md) --- # Examples | pywebview [#](https://pywebview.flowrl.com/3.7/examples/#examples) Examples ================================================================== You can find examples demonstrating features of _pywebview_ in the sidebar. Below there are a couple of non-trivial examples that demonstrate an application architecture. [#](https://pywebview.flowrl.com/3.7/examples/#react-boilerplate) React Boilerplate ------------------------------------------------------------------------------------ [React boilerplate with parcel-bundler (opens new window)](https://github.com/r0x0r/pywebview-react-boilerplate) . A complete React-based boilerplate with installation, usage and building taken care of out of the box. [React boilerplate with create-react-app (opens new window)](https://github.com/dzc0d3r/pywebview-react-boilerplate/) . A complete React-based boilerplate with installation, usage and building taken care of out of the box. [#](https://pywebview.flowrl.com/3.7/examples/#serverless-application) Serverless application ---------------------------------------------------------------------------------------------- [Serverless application (opens new window)](https://github.com/r0x0r/pywebview/tree/docs/examples/todos) A simple todo application that uses serverless architecture. Communication between frontend and backend is provided by built-in API. ![Windows](https://pywebview.flowrl.com/screenshots/todos-windows.png) #### Windows ![macOS](https://pywebview.flowrl.com/screenshots/todos-macos.png) #### macOS ![Linux](https://pywebview.flowrl.com/screenshots/todos-linux.png) #### Linux [#](https://pywebview.flowrl.com/3.7/examples/#http-server-application) HTTP server application ------------------------------------------------------------------------------------------------ [Flask-based application (opens new window)](https://github.com/r0x0r/pywebview/tree/docs/examples/flask_app) In this example communication between frontend and backend is facilitated by a Flask server. --- # Changelog | pywebview [#](https://pywebview.flowrl.com/3.7/changelog#changelog) Changelog ==================================================================== [#](https://pywebview.flowrl.com/3.7/changelog#_3-7) 3.7 --------------------------------------------------------- _Released 04/11/2022_ ### [#](https://pywebview.flowrl.com/3.7/changelog#%E2%9A%A1-features) ⚡ Features * \[All\] New `window.moved` event. Thanks @irtimir ### [#](https://pywebview.flowrl.com/3.7/changelog#%F0%9F%9A%80-improvements) 🚀 Improvements * \[EdgeChromium\] Remove `The system cannot find the file specified - Microsoft Edge WebView2 Runtime Registry path: Computer\HKEY_CURRENT_USER\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}` error message displayed in debug mode. * \[CEF\] error.log is no longer deleted when in debug mode. ### [#](https://pywebview.flowrl.com/3.7/changelog#%F0%9F%90%9E-bug-fixes) 🐞 Bug fixes * \[All\] Fix `evaluate_js_async` crash and program termination prevention. Thanks @detritophage. * \[WinForms\] Fix form initialization for pythonnet 3. Thanks @irtimir * \[CEF\] Fix errorous script execution in `evaluate_js`, so that further script do not get stuck. Thanks @irtimir * \[CEF\] Fix `master uid not found` error on startup. * \[QT\] Remove 'Empty key passed' messages. Thanks @TomFryers * \[QT\] PySide6 backend not working. Thanks @sbbosco * \[QT\] Prevent 'Release of profile requested but WebEnginePage still not deleted. Expect troubles !' message on close. Thanks @sbbosco [#](https://pywebview.flowrl.com/3.7/changelog#_3-6-3) 3.6.3 ------------------------------------------------------------- _Released 05/04/2022_ ### [#](https://pywebview.flowrl.com/3.7/changelog#%F0%9F%90%9E-bug-fixes-2) 🐞 Bug fixes * \[Winforms\] Support for Edge Chromium v100. Thanks @greper. [#](https://pywebview.flowrl.com/3.7/changelog#_3-6-2) 3.6.2 ------------------------------------------------------------- _Released 05/03/2022_ ### [#](https://pywebview.flowrl.com/3.7/changelog#%F0%9F%90%9E-bug-fixes-3) 🐞 Bug fixes * \[Cocoa\] Fix closing window [#](https://pywebview.flowrl.com/3.7/changelog#_3-6-1) 3.6.1 ------------------------------------------------------------- _Released 16/02/2022_ * `Fix` \[CEF\] Exception on start [#](https://pywebview.flowrl.com/3.7/changelog#_3-6) 3.6 --------------------------------------------------------- _Released 15/02/2022_ * `New` \[All\] Python 3.6 is the minimum supported version from now on. * `New` \[All\] `minimized`, `maximized`, `restored`, `resized` events. Thanks @BillBridge for sponsorship. * `New` \[All\] `evaluate_js` async support. `evaluate_js(code, callback)` can evaluate promises via an optional callback parameter. * `New` \[All\] Events moved to its own `window.events` namespace (e.g. `window.loaded` → `window.events.loaded`). Old events are supported throughout 3.x and will be removed in 4.0. * `New` \[All\] `window.resize(width, height, fix_point)` has now an optional parameter fix\_point that controls in respect to which point the window is resized. * `New` \[All\] MSHTML and EdgeHTML are deprecated. No further development will be done on these renderers. * `New` \[Winforms\] Focus webview on start or window activate events. * `New` \[EdgeChromium\] Custom user agent support. * `New` \[EdgeChromium\] Window transparency support. Mouse and keyboards events are not supported in transparent. Thanks @odtian. * `New` \[CEF\] Ability to pass custom CEF browser settings. Thanks @Rolf-MP. * `Improvement` \[EdgeChromium\] Support non-elevated installations of WebView2. Thanks @ultrararetoad. * `Improvement` \[EdgeChromium\] Better support for Edge Chromium runtime detectiom. Thanks @r-muthu-saravanan. * `Improvement` \[EdgeChromium\] WebView2 runtime updated to * `Improvement` \[QT\] Pyside support via PyQT wrapper. Thanks @tshemeng. * `Fix` \[Cocoa\] Make Ctrl-C (SIGINT) work on Cocoa when running from the command line * `Fix` \[EdgeChromium\] Fix \`load\_html. Thanks @sbbosco. * `Fix` \[Cocoa\] Fix cancelling of closing the window in the closing event Thanks @fizzadar. * `Fix` \[QT\] Fix simultaneous calls to JS API. * `Fix` \[GTK\] Fix concurrency issues with get\_size, get\_position and get\_current\_url. [#](https://pywebview.flowrl.com/3.7/changelog#_3-5) 3.5 --------------------------------------------------------- _Released 02/08/2021_ * `New` \[All\] Get information about available screens via new `webview.screens` property. * `New` \[All\] Per window localization. Thanks @fizzadar. * `New` \[All\] Window closing can be cancelled by returning False from a closing event handler. #744. * `Fix` \[All\] Debug mode cannot be set under certain conditions. #628 * `Improvement` \[All\] Selected web renderer printed in Python console in debug mode. * `Improvement` \[All\] JS API serialization logic. Thanks @peter23 * `Improvement` \[EdgeChromium\] Chromium runtime updated to version 1.0.774.44. Thanks @sbbosco. * `Improvement` \[EdgeChromium\] Custom user agent support. * `Fix` \[WinForms\] Icon handling logic to make pywebview compatible with pystray. #720. Thanks @simonrob * `Fix` \[EdgeChromium\] Change webview component to transparent. Thanks @ODtian * `Fix` \[CEF\] Fix exception when destroying window * `Fix` \[Cocoa\] cmd+w bypasses exit confirmation dialogue. #698. Thanks @fizzadar * `Fix` \[Cocoa\] Fix window coordinate calculation logic when moving a window. * `Fix` \[MSHTML\] Fix drag\_region * `Fix` \[MSHTML\] Fix window.alert [#](https://pywebview.flowrl.com/3.7/changelog#_3-4-second-wave) 3.4: Second wave ---------------------------------------------------------------------------------- _Released 04/12/2020_ * `New` \[Windows\] WebView2 Chromium support. Thanks [sbbosco (opens new window)](https://github.com/sbbosco) . [#521 (opens new window)](https://github.com/r0x0r/pywebview/issues/521) . * `Fix` \[All\] Exception with HTML checkboxes and `get_elements`. [#622 (opens new window)](https://github.com/r0x0r/pywebview/issues/622) . * `Fix` \[All\] pystray compatibility. Thanks [AlexCovizzi (opens new window)](https://github.com/AlexCovizzi) . [#486 (opens new window)](https://github.com/r0x0r/pywebview/issues/486) . * `Fix` \[All\] expose methods instead of all callables for JS API objects. Thanks [jgentil (opens new window)](https://github.com/jgentil) . [#629 (opens new window)](https://github.com/r0x0r/pywebview/issues/629) . * `Fix` \[EdgeHTML\] Make returning results of `evaluate_js` more robust. Thanks [sbbosco (opens new window)](https://github.com/sbbosco) . * `Fix` \[QT\] KDE\_FULL\_SESSION not being used. Thanks [Maltzur (opens new window)](https://github.com/Maltzur) . * `Fix` \[Cocoa\] Unicode filenames for input files. * `Improvement` \[Cocoa\] Only install the specific `pyobjc` packages required. Thanks [Fizzadar (opens new window)](https://github.com/fizzadar) . * `Improvement` \[Cocoa\] Add support for default document navigation and window handling shortcut keys . Thanks [ikhmyz (opens new window)](https://github.com/ikhmyz) and [Fizzadar (opens new window)](https://github.com/fizzadar) [#](https://pywebview.flowrl.com/3.7/changelog#_3-3-5) 3.3.5 ------------------------------------------------------------- _Released 26/09/2020_ * `Fix` \[EdgeHTML\] Server middleware handling * `Fix` \[EdgeHTML\] file:// url handling [#](https://pywebview.flowrl.com/3.7/changelog#_3-3-4) 3.3.4 ------------------------------------------------------------- _Released 18/09/2020_ * `Fix` \[EdgeHTML\] Fix content not displaying with local URLs or local HTTP server * `Fix` \[Cocoa\] Fixes arrow keys not responding in text input fields. Thanks [awesomo4000 (opens new window)](https://github.com/awesomo4000) [#](https://pywebview.flowrl.com/3.7/changelog#_3-3-3) 3.3.3 ------------------------------------------------------------- _Released 08/08/2020_ * `Fix` \[Cocoa\] Save dialog not working [#578 (opens new window)](https://github.com/r0x0r/pywebview/issues/578) . * `Fix` \[Cocoa\] Error sound being played when pressing keys on macOS [#566 (opens new window)](https://github.com/r0x0r/pywebview/issues/566) . [#](https://pywebview.flowrl.com/3.7/changelog#_3-3-2) 3.3.2 ------------------------------------------------------------- _Released 28/07/2020_ * `Fix` \[All\] Load html triggers error - resolve\_url() missing 1 required positional argument: 'should\_serve' [#562 (opens new window)](https://github.com/r0x0r/pywebview/issues/562) . * `Fix` \[Cocoa/GTK\] Access window size on closing [#573 (opens new window)](https://github.com/r0x0r/pywebview/issues/573) . * `Fix` \[GTK\] Save file dialog now returns a string instead of a tuple. [#](https://pywebview.flowrl.com/3.7/changelog#_3-3-1) 3.3.1 ------------------------------------------------------------- _Released 01/07/2020_ * `Fix` \[WinForms\] TypeError : 'str' value cannot be converted to System.Drawing.Color [#560 (opens new window)](https://github.com/r0x0r/pywebview/issues/560) . [#](https://pywebview.flowrl.com/3.7/changelog#_3-3-detroit-edition) 3.3: Detroit Edition ------------------------------------------------------------------------------------------ _Released 29/06/2020_ * `New` \[All\] Brand-new WSGI based internal HTTP server. Thanks [@astronouth7303 (opens new window)](https://github.com/astronouth7303) . * `New` \[All\] Transparent window. Not available on Windows. * `New` \[All\] Allow _pywebview_ window to be on top of other windows. * `New` \[All\] Custom window drag region using CSS classes. Thanks [@Fizzadar (opens new window)](https://github.com/Fizzadar) . * `New` \[All\] Custom user-agent support. Thanks [@tognee (opens new window)](https://github.com/tognee) . * `Fix` \[All\] Python function not triggered using JS [#458 (opens new window)](https://github.com/r0x0r/pywebview/issues/458) . * `Fix` \[All\] window methods do not work in `loaded` event [#528 (opens new window)](https://github.com/r0x0r/pywebview/issues/528) . * `Fix` \[Cocoa\] Caption bar and window control buttons are now hidden in frameless mode. * `Fix` \[CEF\] CEF window resize hang [#484 (opens new window)](https://github.com/r0x0r/pywebview/issues/484) . * `Fix` \[MSHTML\] Fix easy drag in frameless mode. * `Fix` \[EdgeHTML\] Do not show admin prompt for non-local URLs. * `Fix` \[GTK\] Fix threading issues with recentish versions of PyGObject * `Fix` \[QT\] Fix opening web inspecting in debug mode [#](https://pywebview.flowrl.com/3.7/changelog#_3-2-humate-edition) 3.2: Humate Edition ---------------------------------------------------------------------------------------- _Released 24/01/2020_ * `New` \[All\] Window x, y, width and height properties to retrieve coordinates and dimensions of the window. Thanks [@Fizzadar (opens new window)](https://github.com/Fizzadar) * `New` \[All\] `window.expose(func)` an ability to expose an arbitrary function to the JS realm, also during the runtime. * `Improvement` \[All\] JS API methods can now accept an arbitrary number of arguments * `Improvement` \[All\] Exceptions thrown in a JS API method is now raised in Javascript via its promise. * `Improvement` \[All\] Exceptions thrown in window event handlers are now caught and logged. * `Improvement` \[All\] Random port assigned by the built-in HTTP server can be retrieved via `webview.http_server.port` * `Improvement` \[QT\] Microphone/webcam are enabled by default. Thanks [@dtcooper (opens new window)](https://github.com/dtcooper) * `Improvement` \[QT\] Default debugger port is changed to 8228. Thanks [@melvinkcx (opens new window)](https://github.com/melvinkcx) * `Improvement` \[CEF\] Ability to pass custom CEF settings via `webview.platforms.cef.settings`. See [example](https://pywebview.flowrl.com/3.7/examples/cef.html) for details. * `Fix` \[All\] Built-in HTTP server is properly restarted when using `window.load_url` * `Fix` \[Cocoa\] New window position is correctly calculated when using `window.move` * `Fix` \[EdgeHTML\] `window.alert` fix [#](https://pywebview.flowrl.com/3.7/changelog#_3-1-windows-edition) 3.1: Windows Edition ------------------------------------------------------------------------------------------ _Released 04/11/2019_ * `New` \[All\] Window minimize/restore functionality. Ability to show window minimized on startup. * `New` \[All\] Window hide/show functionality. Ability to show window hidden on startup. * `New` \[All\] Window move functionality. Ability to set window coordinates on startup. Thanks @adbenitez. * `New` \[All\] New `window.pywebviewready`DOM event that is thrown when `window.pywebview` is available. * `New` \[All\] Links opened via `window.open` are opened in a new browser window. * `Fix` \[All\] Fix concurrent invocations of JS API functions. * `Fix` \[All\] Fix unescaped single quote in JS API calls. * `Fix` \[All\] Built-in HTTP server is now multi-threaded. This fixes stalling HTTP requests in some cases. * `Improvement` \[All\] `window.set_window_size` is deprecated in favour to `window.resize`. * `Improvement` \[All\] Exceptions are now handled in JS API functions and rerouted to the function promise catch method. * `Improvement` \[All\] Suppress built-in HTTP server logging. Logging is active only in the debug mode. * `Fix` \[CEF\] Fix deadlock occurring when trying to access `window.pywebview` object right after the window is created. * `Fix` \[CEF\] High DPI fix resulting in a small window appearing inside the main window, * `Fix` \[EdgeHTML\] Unicode error when loading HTML. * `Fix` \[MSHTML\] `get_elements` failing. * `Fix` \[MSHTML\] `console.log` not writing to Python console in debug mode. * `Fix` \[MSHTML\] Forcing MSHTML via `gui=mshtml` is now possible. ¯\\\_(ツ)\_/¯ ![Windows 3.1](https://pywebview.flowrl.com/windows31.png) [#](https://pywebview.flowrl.com/3.7/changelog#_3-0-2) 3.0.2 ------------------------------------------------------------- _Released 17/08/2019_ * `Fix` \[All\] Prevent JSON like strings being converted to JSON objects when returning JS API calls. #352 * `Fix` \[Windows\] HTTP server is now used by default for local URLs and HTML for EdgeHTML. This fixes a PermissionDenied error, when the directory the executable is in is not writable. * `Fix` \[Tests\] Tests now fail on an exception occurring in a thread. [#](https://pywebview.flowrl.com/3.7/changelog#_3-0-1) 3.0.1 ------------------------------------------------------------- _Released 25/07/2019_ * `Fix` \[All\] Don't escape line breaks in result of js\_bridge\_call. Thanks @kvasserman. * `Fix` \[Windows\] Support for Pyinstaller noconsole mode * `Fix` \[Windows\] Fix Windows version detection with frozen executables. * `Fix` \[Windows\] Open folder dialog now supports `directory` argument. * `Fix` \[QT\] Workaround for segmentation fault on closing the main window. Thanks @kvasserman. * `Fix` \[Pytest\] Fix for pytest warning about invalid escape sequence [#](https://pywebview.flowrl.com/3.7/changelog#_3-0) 3.0 --------------------------------------------------------- _Released 11/07/2019_ * `New` \[All\] New API. The API is not compatible with older versions of _pywebview_. See https://pywebview.flowrl.com for usage details. #272 * `New` \[All\] Built-in HTTP server. #260 * `New` \[All\] Autogenerated CSRF token exposed as `window.pywebview.token`. #316 * `New` \[All\] `get_elements` function to retrieve DOM nodes. #292 * `New` \[All\] New events system that lets you to subscribe to events. `loaded` and `shown` events are implemented. #201 * `New` \[Windows\] EdgeHTML support. Thanks @heavenvolkoff. #243 * `Fix` \[Windows\] Fullscreen mode. #338 * `Fix` \[GTK\] Better Javascript support for recent version of WebKit2 * `Fix` \[CEF\] Support for PyInstaller in onefile mode [#](https://pywebview.flowrl.com/3.7/changelog#_2-4) 2.4 --------------------------------------------------------- _Released 17/02/2019_ * `New` \[All\] Support for frameless windows. * `Fix` \[Windows\] Fix broken installation of v2.3 [#](https://pywebview.flowrl.com/3.7/changelog#_2-3) 2.3 --------------------------------------------------------- _Released 12/02/2019_ * `New` \[All\] Ability to resize window after creation `webview.set_window_size(width, height)`. Thanks @aprowe #274 * `New` \[Windows\] Chrome Embedded Framework (CEF) support #15 * `Improvement` \[All\] _pywebview_ does not interfer with Python's logger configuration #295 * `Fix` \[All\] Empty DOM issues when window is created without a URL #285 * `Improvement` \[macOS\] Web renderer upgraded to WKWebView * `Improvement` \[macOS\] Add support for Mojave dark mode * `Fix` \[macOS\] Problem with handling paths containing spaces #283 * `Fix` \[QT\] Better support for QTWebKit and QTWebChannel #304 * `Improvement` \[QT\] Remove support for QT4 * `Fix` \[GTK\] Thrown exception not Python 2 compatible #277 [#](https://pywebview.flowrl.com/3.7/changelog#_2-2-1) 2.2.1 ------------------------------------------------------------- _Released 24/10/2018_ * `Fix` Dependency installation * `New` Reintroduce \[qt\] extra require switch [#](https://pywebview.flowrl.com/3.7/changelog#_2-2) 2.2 --------------------------------------------------------- _Released 23/10/2018_ * `New` Brand new documentation at https://pywebview.flowrl.com * `Improvement` Simplify installation. Now pywebview can be installed by `pip install pywebview`. Dependencies will be resolved and installed automatically * `Improvement` \[GTK\] Update to WebKit2 [#](https://pywebview.flowrl.com/3.7/changelog#_2-1) 2.1 --------------------------------------------------------- Released 16/09/2018 * `New` \[All\] Introduce `PYWEBVIEW_GUI` environment variable and `webview.config.gui` property. Acceptable values are are `qt`, `gtk` and `win32`. `USE_QT` and `USE_WIN32` is deprecated. * `Fix` \[Cocoa\] Closing main window does not result in program termination * `Fix` \[All\] New main window re-creation after closing. #229 * `Fix` \[QT\] Debug mode #233 * `Fix` \[Cocoa/Windows\] Preserve JS API on page reload * `Fix` \[Windows\] `toggle_fullscreen()` function #232. Thanks @lt94 * `Fix` \[Windows\] `load_css()` function. Thanks @wormius. [#](https://pywebview.flowrl.com/3.7/changelog#_2-0-3) 2.0.3 ------------------------------------------------------------- Released 16/05/2018 * `Fix` \[QT\] Fix a deadlock preventing QT implementation from starting * `Fix` \[QT\] QT is set to default on QT-based systems [#](https://pywebview.flowrl.com/3.7/changelog#_2-0-1-2-0-2) 2.0.1/2.0.2 ------------------------------------------------------------------------- Released 08/05/2018 * `Fix` \[Winforms\] Fix installation of dlls [#](https://pywebview.flowrl.com/3.7/changelog#_2-0) 2.0 --------------------------------------------------------- Released 28/04/2018 * `New` \[All\] Multi-window support * `New` \[All\] Ability to call Python code from Javascript via `window.pywebview.api` * `New` \[All\] Debug mode. Web inspector for Cocoa/GTK/QT and basic debug information for WinForms. * `New` \[All\] File filter support in `create_file_dialog` * `New` \[All\] `target='_blank'` links are now opened in an external browser * `New` \[All\] Change window title via a `set_title` function #159 * `New` \[All\] `load_css` function * `New` \[All\] Support for relative local URLs in `create_window` / `load_html`. Linked local resources are resolved as well. #186 * `New` \[All\] `todos` example app demonstrating js api and relative local URLs. * `New` \[All\] Text select in the webview window is disabled by default. Added `text_select` argument to `create_window` function. * `New` \[QT\] OpenBSD 6.x support #213. Thanks @hucste. * `Fix` \[All\] `base_uri` parameter of `load_html` defaults to the directory of the entry script * `Fix` \[All\] Consistent return types with `evaluate_js` across different platforms #175 * `Fix` \[All\] Various concurrency issues and deadlocks * `Fix` \[Winforms\] Hide `Message from webpage` when using `alert` Javascript function #150 * `Fix` \[Winforms\] Support for high DPI #179 * `Fix` \[QT\] Support for QT 5.10 #171. Thanks @adbenitez * `Fix` \[QT\] Deprecate QT4. Starting from this version new features won't be tested on QT4 and support will be removed in the future. [#](https://pywebview.flowrl.com/3.7/changelog#_1-8) 1.8 --------------------------------------------------------- Released 29/10/2017 * pywebview has the official logo * @shivaprsdv is now an official maintainer of the project * `New` \[All\] Add an ability to run Javascript code using `evaluate_js` function * `Fix` \[Cocoa\] Implement missing webview components (file input dialog, alert()/confirm() JS functions) * `Fix` \[Winforms\] Fix issue with non-responsive UI when a loading screen background color is used * `Fix` \[Winforms\] Add support for Del and Ctrl+A keys in input elements. * `New` \[QT\] QT5 is now prefererred over QT4 * `Fix` \[QT\] Fix return parameters of `create_file_dialog` to have the same format as on other platforms * `Fix` \[GTK\] Better threading model. Thanks to @jorants #121 [#](https://pywebview.flowrl.com/3.7/changelog#_1-7) 1.7 --------------------------------------------------------- Released 08/06/2017 * `New` \[All\] Add a basic test suite and continuous integration. #88 * `New` \[All\] Add a background\_color parameter to create\_window, which specifies the default color of the webview window. Refer to examples/loading\_indicator.py for example use. Thanks to @shivaprsdv. #90 * `New` \[Cocoa\] Disable backspace navigation. Thanks to @shivaprsdv. #102 * `New` \[Cocoa\] Implementation of window.print() and window.confirm method. Thanks to @shivaprsdv. #97 * `Fix` \[Cocoa\] Fix non-existing localization string in save file dialog * `New` \[Winforms\] Disable all the shortcut keys of web navigation * `Fix` \[Winforms\] Fix load\_html failing sometimes due thread violation * `Fix` \[GTK\] Implement fall-through to QT, when GTK is present, but not GTK.WebKit. [#](https://pywebview.flowrl.com/3.7/changelog#_1-6) 1.6 --------------------------------------------------------- Released 29/03/2017 * `New` \[All\] Quit confirmation dialog #31 * `New` \[All\] webview.config can be used using the dot notation (ie. webview.config.use\_win32 = True) * `New` \[Winforms\] Disable context menu * `Fix` \[Winforms\] Application icon is now visible in the application window when frozen with PyInstaller #91 * `Fix` \[Mac\] load\_html() is invoked as soon as the webview is ready #93 * `Fix` \[QT\] get\_current\_url() not working due a typo. Thanks @maroc81. #85 * `Fix` \[GTK\] Better exception handling when GTK is not found #94 * `Fix` \[GTK\] destroy\_window() #95 [#](https://pywebview.flowrl.com/3.7/changelog#_1-5) 1.5 --------------------------------------------------------- Released 09/02/2017 * `New` \[All\] toggle\_fullscreen function #52 * `New` \[All\] get\_current\_url function #76 * `New` \[Winforms\] Javascript errors are now suppressed * `Fix` \[Winforms\] Fixed resizable=False not being enforced #73 [#](https://pywebview.flowrl.com/3.7/changelog#_1-4) 1.4 --------------------------------------------------------- Released 14/01/2017 * `New` \[All\] pip installation now supports choosing what dependencies to install. See README for more information. Thanks @josePhoenix * `New` \[All\] Localization support. Refer to `examples/localization.py` for an example use * `New` \[Mac\] QT5 support * `Fix` \[Windows\] File dialogs are now attached to the main window * `Fix` \[Windows\] Pyinstaller crash issue with an icon in Windows Forms [#](https://pywebview.flowrl.com/3.7/changelog#_1-3) 1.3 --------------------------------------------------------- Released 31/10/2016 * `New` \[Cocoa\] Added View -> Fullscreen standard menu item. Thanks to @bastula. * `New` \[Cocoa\] Added About menu item #45. Thanks to @bastula. * `New` \[Windows\] An application icon for Windows Forms * `Fix` \[Windows\] Removed unnecessary pywin32 dependencies from Windows Forms #60 * `Fix` \[Linux\] Thread violation in load\_url in GTK implementation #59 [#](https://pywebview.flowrl.com/3.7/changelog#_1-2-2) 1.2.2 ------------------------------------------------------------- Released 10/10/2016 * `Fix` \[All\] Python 2 compatibility issue in Flask Example (#52). Thanks to @bastula. * `Fix` \[Windows\] Python 3 compatibility issue in Windows Forms implementation (#51) * `Fix` \[Linux\] Resizing width/height: 100% problem on GTK (#53). Thanks to @klausweiss. [#](https://pywebview.flowrl.com/3.7/changelog#_1-2-1) 1.2.1 ------------------------------------------------------------- Released 29/09/2016 * `Fix` \[Linux\] GTK window failing to open. Thanks to @lchish. #50 [#](https://pywebview.flowrl.com/3.7/changelog#_1-2) 1.2 --------------------------------------------------------- Released 27/09/2016 * `New` \[All\] Introduced `load_html` function that allows dynamic loading of HTML code, instead of a URL. Implemented for all platforms except Win32 (use Windows Forms). Thanks to @ysobolev #39 * `New` \[All\] Added an example of a Flask-based application skeleton. The example can be found in `examples/flask_app` * `New` \[Windows\] Windows Forms based implementation of webview window. Requires pythonnet. * `New` \[Windows\] Introduced config\["USE\_WIN32"\] variable that lets you choose between Win32 and Windows Forms. Default to True (Windows Forms will be made as default in the future) * `Fix` \[Windows/Linux\] Got rid of installation dependencies on Windows and Linux. The dependencies now have to be installed by hand and the choice of dependencies is left to user * `Fix` \[Linux\] Compatibility with Qt 5.5. Thanks to @danidee10. #48 [#](https://pywebview.flowrl.com/3.7/changelog#_1-1) 1.1 --------------------------------------------------------- Released 08/06/2016 * `New` \[OSX\] Add a default application menu #35. Thanks @cuibonobo * `New` \[Linux\] GTK is made as default and pypi dependency added. USE\_GTK environment variable is also deprecated. To use QT, set `webview.config["USE_QT"] = True` * `Fix` \[Windows\] Open folder of create\_file\_dialog now returns Unicode, instead of byte encoding. [#](https://pywebview.flowrl.com/3.7/changelog#_1-0-2) 1.0.2 ------------------------------------------------------------- Released 19/05/2016 * `Fix` \[Windows\] Fix a dead-lock that sometimes occurs on a window creation, when used with a HTTP server running in a separate thread. [#](https://pywebview.flowrl.com/3.7/changelog#_1-0-1) 1.0.1 ------------------------------------------------------------- Released 17/05/2016 * `Fix` \[Windows\] PyInstaller: Icon not found #29 [#](https://pywebview.flowrl.com/3.7/changelog#_1-0) 1.0 --------------------------------------------------------- Released 12/02/2016 * `New` \[All\] Add an ability to programmatically destroy a webview window * `Fix` \[Windows\] Fullscreen mode * `Fix` \[Windows\] Change setup.py to use pypiwin32 #22 * `Fix` \[Windows\] Relative import of win32\_gen fixed on Python 3 #20. Thanks to @yoavram for the contribution * `Fix` \[Windows\] FileNotFound exception on Windows 2003. Thanks to @jicho for the contribution * `Fix` \[OSX\] Non-SSL URLs are allowed by default on El Capitan. Thanks to @cr0hn for the contribution [#](https://pywebview.flowrl.com/3.7/changelog#_0-9) 0.9 --------------------------------------------------------- Released 27/11/2015 * `New` \[All\] Right click context menu is disabled #12 * `New` \[All\] Window minimum size constraints #13 * `New` \[All\] Save file dialog * `New` \[All\] Added `directory` and `save_filename` parameters to `create_file_dialog` * `New` \[All\] An option to set a default directory in a file dialog * `New` \[GTK\] Introduced USE\_GTK environment variable. When set, GTK is preferred over QT. * `Fix` \[Windows\] Webview scrollbar sizing with a non-resizable window * `Fix` \[Windows\] Add support for application icon #9 * `Fix` \[Windows\] Disable logging spam for comtypes [#](https://pywebview.flowrl.com/3.7/changelog#_0-8-4) 0.8.4 ------------------------------------------------------------- * `Fix` \[Windows\] Invisible scrollbars * `Fix` \[Windows\] Fullscreen mode [#](https://pywebview.flowrl.com/3.7/changelog#_0-8-3) 0.8.3 ------------------------------------------------------------- * `Fixed` #10 Underlying browser does not resize with window under windows [#](https://pywebview.flowrl.com/3.7/changelog#_0-8-2) 0.8.2 ------------------------------------------------------------- Released on 08/10/2015 * `Fixed` Pressing close window button terminates the whole program on OSX [#](https://pywebview.flowrl.com/3.7/changelog#_0-8) 0.8 --------------------------------------------------------- Released on 06/10/2015 * `New` Support for native open file / open folder dialogs * `Fixed` #6 FEATURE\_BROWSER\_EMULATION not in winreg.HKEY\_CURRENT\_USER. Thanks to @frip for the fix. [#](https://pywebview.flowrl.com/3.7/changelog#_0-7) 0.7 --------------------------------------------------------- Released on 08/04/2015 * `Fixed` Python 3 compatibility in Win32 module (thanks @Firnagzen) #3 * `Fixed` Floating values for window dimensions causing issues on Windows XP (thanks @Firnagzen) #4 * `Fixed` Correct IE version registry key on Windows XP (thanks @Firnagzen) #5 [#](https://pywebview.flowrl.com/3.7/changelog#_0-6) 0.6 --------------------------------------------------------- Released on 11/02/2015 * `Fixed` A problem preventing from creating a window on Windows [#](https://pywebview.flowrl.com/3.7/changelog#_0-5) 0.5 --------------------------------------------------------- Released on 30/11/2014 * `New` Windows support * `New` GTK3 support * `New` pip installation * `New` Fullscreen mode [#](https://pywebview.flowrl.com/3.7/changelog#_0-1) 0.1 --------------------------------------------------------- Released on 20/11/2014 * First release * Linux and OSX support --- # Documentation | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/documentation#documentation) Documentation ============================================================================================= One way to contribute is to improve documentation on this side. Each page has a 'Help us improve this page' link at the bottom of the page. By clicking the link you can create a pull request with your changes. You need a Github account to edit pages. ← [Donating](https://pywebview.flowrl.com/3.7/contributing/donating.html) --- # Application architecture | pywebview [#](https://pywebview.flowrl.com/3.7/guide/architecture#application-architecture) Application architecture =========================================================================================================== There are two ways to build your application using _pywebview_: 1. By running a local web server 2. Serverless with _pywebview_'s JS API or `window.expose` and serving local files. [#](https://pywebview.flowrl.com/3.7/guide/architecture#local-web-server) Local web server ------------------------------------------------------------------------------------------- Running a local web server is a traditional way to build your local application. This way everything is served from a local web server and _pywebview_ points to the URL provided by the server. In this model the server is responsible for both serving static contents and handling API calls. When building an application using a web server, you should protect your API calls against CSRF attacks. See [security](https://pywebview.flowrl.com/3.7/guide/security.html) for more information. See an example [Flask-based application (opens new window)](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) **Pros**: * Ability to pack an existing web application as a local one. * Easier debugging with an external browser. **Cons** * Has to rely on a third party server software for client-server communication. * Security considerations must be taken into account [#](https://pywebview.flowrl.com/3.7/guide/architecture#serverless) Serverless ------------------------------------------------------------------------------- Another way to build an application is to use _pywebview_'s provided JS API or `windows.expose` and serve static files locally. _pywebview_ offers a simple built-in web server that is good enough for serving local files. To use a local web server, set url to a local file and start the application with `webview.start(http_server=True)`. Note that the built-in HTTP server serves only local files and does not offer any API calls. Refer to [interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) for details on how to pass data between Python and Javascript. See an example [serverless application (opens new window)](https://github.com/r0x0r/pywebview/tree/master/examples/todos) **Pros**: * No external dependencies * More straightforward architecture * No risk of CSRF attacks **Cons** * Debugging has to be done inside the application using provided debugging tools * EdgeHTML cannot serve local files. ← [API](https://pywebview.flowrl.com/3.7/guide/api.html) [Debugging](https://pywebview.flowrl.com/3.7/guide/debugging.html) → --- # CSS load | pywebview [#](https://pywebview.flowrl.com/3.7/examples/css_load#css-load) CSS load ========================================================================== Change window background color by loading CSS import webview def load_css(window): window.load_css('body { background: red !important; }') if __name__ == '__main__': window = webview.create_window('Load CSS Example', 'https://pywebview.flowrl.com/hello') webview.start(load_css, window) ← [Change URL](https://pywebview.flowrl.com/3.7/examples/change_url.html) [Quit confirmation dialog](https://pywebview.flowrl.com/3.7/examples/close_confirm.html) → --- # Security | pywebview [#](https://pywebview.flowrl.com/3.7/guide/security#security) Security ======================================================================= When using a local web server, you must protect your API from unauthorized access. [CSRF attacks (opens new window)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) can be a major problem if API is not protected in an adequate matter. _pywebview_ generates a session-unique token that is exposed both to Python `webview.token` and DOM `window.pywebview.token`. See [Flask app (opens new window)](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) for an example. For building a custom solution refer to [this document (opens new window)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet) for API securing approaches. A library like [flask-seasurf (opens new window)](https://flask-seasurf.readthedocs.io/en/latest/) alongside Flask can be used too. ← [Freezing](https://pywebview.flowrl.com/3.7/guide/freezing.html) [Virtual environment](https://pywebview.flowrl.com/3.7/guide/virtualenv.html) → --- # Debugging | pywebview [#](https://pywebview.flowrl.com/3.7/examples/debug#debugging) Debugging ========================================================================= To open up debugging console, right click on an element and select Inspect. import webview if __name__ == '__main__': webview.create_window('Debug window', 'https://pywebview.flowrl.com/hello') webview.start(debug=True) ← [Quit confirmation dialog](https://pywebview.flowrl.com/3.7/examples/close_confirm.html) [Destroy window](https://pywebview.flowrl.com/3.7/examples/destroy_window.html) → --- # Destroy window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/destroy_window#destroy-window) Destroy window -------------------------------------------------------------------------------------------- Programmatically destroy created window after five seconds. import webview import time def destroy(window): # show the window for a few seconds before destroying it: time.sleep(5) print('Destroying window..') window.destroy() print('Destroyed!') if __name__ == '__main__': window = webview.create_window('Destroy Window Example', 'https://pywebview.flowrl.com/hello') webview.start(destroy, window) print('Window is destroyed') ← [Debugging](https://pywebview.flowrl.com/3.7/examples/debug.html) [Events](https://pywebview.flowrl.com/3.7/examples/events.html) → --- # Virtual environment | pywebview [#](https://pywebview.flowrl.com/3.7/guide/virtualenv#virtual-environment) Virtual environment =============================================================================================== If you create a virtual environment using the built-in Python on macOS, a pywebview window will have issues with keyboard focus and Cmd+Tab. The issue can be avoided by using other Python installation as described [here (opens new window)](https://virtualenv.pypa.io/en/stable/userguide/#using-virtualenv-without-bin-python) . For example to use Python 3 via [Homebrew (opens new window)](https://brew.sh/) . brew install python3 virtualenv pywebview_env -p python3 ← [Security](https://pywebview.flowrl.com/3.7/guide/security.html) [Web engine](https://pywebview.flowrl.com/3.7/guide/renderer.html) → --- # Web engine | pywebview [#](https://pywebview.flowrl.com/3.7/guide/renderer#web-engine) Web engine =========================================================================== The following renderers are used on each platform | Platform | Code | Renderer | Provider | Browser compatibility | | --- | --- | --- | --- | --- | | GTK | gtk | WebKit | WebKit2 | | | macOS | | WebKit | WebKit.WKWebView (bundled with OS) | | | QT | qt | WebKit | QtWebEngine / QtWebKit | | | Windows | edgechromium | Chromium | \> .NET Framework 4.6.2 and Edge Runtime installed | Ever-green Chromium | | Windows | edgehtml | EdgeHTML | \> .NET Framework 4.6.2 and Windows 10 build 17110 | | | Windows | mshtml | MSHTML | MSHTML via .NET / System.Windows.Forms.WebBrowser | IE11 (Windows 10/8/7) | | Windows | cef | CEF | CEF Python | Chrome 66 | On Windows renderer is chosen in the following order: `edgechromium`, `edgehtml`, `mshtml`. `mshtml` is the only renderer that is guaranteed to be available on any system. Note that Edge Runtime must be installed in order to use Edge Chromium on Windows. You can download it from [here (opens new window)](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . Distribution guidelines are found [here (opens new window)](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) . To change a default renderer set either `PYWEBVIEW_GUI` environment variable or pass the rendered value to `webview.start(gui=code)` function parameter. Check for available values in the Code column from the table above. For example to use CEF on Windows PYWEBVIEW_GUI=cef or import webview webview.start(gui='cef') If you wish to pass custom settings to CEF, refer to [this example](https://pywebview.flowrl.com/3.7/examples/cef.html) To force QT on Linux systems PYWEBVIEW_GUI=qt or import webview webview.start(gui='qt') [#](https://pywebview.flowrl.com/3.7/guide/renderer#known-issues-and-limitations) Known issues and limitations =============================================================================================================== [#](https://pywebview.flowrl.com/3.7/guide/renderer#gtk-webkit2) GTK WebKit2 ----------------------------------------------------------------------------- * Versions of WebKit2 older than 2.2 has a limitation of 1000 characters of the Javascript result returned by `evaluate_js`. `get_elements` is not supported for this reason. [#](https://pywebview.flowrl.com/3.7/guide/renderer#qtwebkit) QtWebKit ----------------------------------------------------------------------- * Debugging is not supported [#](https://pywebview.flowrl.com/3.7/guide/renderer#edgehtml) EdgeHTML ----------------------------------------------------------------------- * `file://` URLs are not fully supported. While such URLs can be loaded, associated resources such as images or stylesheets cannot. * Destroying a window via `window.destroy()` and starting a new instance will crash the program. * Running the program under elevated privileges will throw an exception. * Access to localhost URLs is restricted by default. To overcome this the LoopbackExempt settings are modified on _pywebview_ launch, which triggers a UAC prompt. This only happens once and only if LoopbackExempt setting is not set. You can manually set this setting beforehand to avoid UAC: `checknetisolation LoopbackExempt -a -n="Microsoft.Win32WebViewHost_cw5n1h2txyewy"` (must be run as an admin). ← [Virtual environment](https://pywebview.flowrl.com/3.7/guide/virtualenv.html) --- # Events | pywebview [#](https://pywebview.flowrl.com/3.7/examples/events#events) Events -------------------------------------------------------------------- Subscribe and unsubscribe to pywebview events. import webview import time """ This example demonstrates how to handle pywebview events. """ def on_closed(): print('pywebview window is closed') def on_closing(): print('pywebview window is closing') def on_shown(): print('pywebview window shown') def on_minimized(): print('pywebview window minimized') def on_restored(): print('pywebview window restored') def on_maximized(): print('pywebview window maximized') def on_loaded(): print('DOM is ready') # unsubscribe event listener webview.windows[0].loaded -= on_loaded webview.windows[0].load_url('https://pywebview.flowrl.com/hello') def on_resized(width, height): print('pywebview window is resized. new dimensions are {width} x {height}'.format(width=width, height=height)) def on_moved(x, y): print('pywebview window is moved. new coordinates are x: {x}, y: {y}'.format(x=x, y=y)) if __name__ == '__main__': window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/', confirm_close=True) window.events.closed += on_closed window.events.closing += on_closing window.events.shown += on_shown window.events.loaded += on_loaded window.events.minimized += on_minimized window.events.maximized += on_maximized window.events.restored += on_restored window.events.resized += on_resized window.events.moved += on_moved webview.start() ← [Destroy window](https://pywebview.flowrl.com/3.7/examples/destroy_window.html) [Frameless window](https://pywebview.flowrl.com/3.7/examples/frameless.html) → --- # HTML load | pywebview [#](https://pywebview.flowrl.com/3.7/examples/html_load#html-load) HTML load ============================================================================= Display content by loading HTML on the fly. import webview import time def load_html(window): time.sleep(5) window.load_html('

This is dynamically loaded HTML

') if __name__ == '__main__': window = webview.create_window('Load HTML Example', html='

This is initial HTML

') webview.start(load_html, window) ← [Hide / show window](https://pywebview.flowrl.com/3.7/examples/hide_window.html) [Javascript evaluation](https://pywebview.flowrl.com/3.7/examples/js_evaluate.html) → --- # Javascript evaluation | pywebview [#](https://pywebview.flowrl.com/3.7/examples/js_evaluate#javascript-evaluation) Javascript evaluation ======================================================================================================= Evaluate Javascript from Python code. import webview def evaluate_js(window): result = window.evaluate_js( r""" var h1 = document.createElement('h1') var text = document.createTextNode('Hello pywebview') h1.appendChild(text) document.body.appendChild(h1) document.body.style.backgroundColor = '#212121' document.body.style.color = '#f2f2f2' // Return user agent 'User agent:\n' + navigator.userAgent; """ ) print(result) if __name__ == '__main__': window = webview.create_window('Run custom JavaScript') webview.start(evaluate_js, window) ← [HTML load](https://pywebview.flowrl.com/3.7/examples/html_load.html) [Javascript API](https://pywebview.flowrl.com/3.7/examples/js_api.html) → --- # Loading animation | pywebview [#](https://pywebview.flowrl.com/3.7/examples/loading_animation#loading-animation) Loading animation ===================================================================================================== Create a loading animation that is displayed before application is loaded. import webview html = """
Loading...

Content is loaded!

""" if __name__ == '__main__': window = webview.create_window('Loading Animation', html=html, background_color='#333333') webview.start() ← [Javascript API](https://pywebview.flowrl.com/3.7/examples/js_api.html) [Link types](https://pywebview.flowrl.com/3.7/examples/links.html) → --- # Localization | pywebview [#](https://pywebview.flowrl.com/3.7/examples/localization#localization) Localization ====================================================================================== Localize system text string used by pywebview. For a full list of used string, refer to the `webview/localization.py` file. # -*- coding: utf-8 -*- import webview if __name__ == '__main__': localization = { 'global.saveFile': u'Сохранить файл', 'cocoa.menu.about': u'О программе', 'cocoa.menu.services': u'Cлужбы', 'cocoa.menu.view': u'Вид', 'cocoa.menu.hide': u'Скрыть', 'cocoa.menu.hideOthers': u'Скрыть остальные', 'cocoa.menu.showAll': u'Показать все', 'cocoa.menu.quit': u'Завершить', 'cocoa.menu.fullscreen': u'Перейти ', 'windows.fileFilter.allFiles': u'Все файлы', 'windows.fileFilter.otherFiles': u'Остальлные файльы', 'linux.openFile': u'Открыть файл', 'linux.openFiles': u'Открыть файлы', 'linux.openFolder': u'Открыть папку', } webview.create_window('Localization Example', 'https://pywebview.flowrl.com/hello') webview.start(localization=localization) ← [Link types](https://pywebview.flowrl.com/3.7/examples/links.html) [Minimum window size](https://pywebview.flowrl.com/3.7/examples/min_size.html) → --- # Javascript API | pywebview [#](https://pywebview.flowrl.com/3.7/examples/js_api#javascript-api) Javascript API ==================================================================================== Create an application without a HTTP server. The application uses Javascript API object to communicate between Python and Javascript. import threading import time import sys import random import webview html = """

JS API Example

pywebview is not ready






""" class Api: def __init__(self): self.cancel_heavy_stuff_flag = False def init(self): response = { 'message': 'Hello from Python {0}'.format(sys.version) } return response def getRandomNumber(self): response = { 'message': 'Here is a random number courtesy of randint: {0}'.format(random.randint(0, 100000000)) } return response def doHeavyStuff(self): time.sleep(0.1) # sleep to prevent from the ui thread from freezing for a moment now = time.time() self.cancel_heavy_stuff_flag = False for i in range(0, 1000000): _ = i * random.randint(0, 1000) if self.cancel_heavy_stuff_flag: response = {'message': 'Operation cancelled'} break else: then = time.time() response = { 'message': 'Operation took {0:.1f} seconds on the thread {1}'.format((then - now), threading.current_thread()) } return response def cancelHeavyStuff(self): time.sleep(0.1) self.cancel_heavy_stuff_flag = True def sayHelloTo(self, name): response = { 'message': 'Hello {0}!'.format(name) } return response def error(self): raise Exception('This is a Python exception') if __name__ == '__main__': api = Api() window = webview.create_window('API example', html=html, js_api=api) webview.start() ← [Javascript evaluation](https://pywebview.flowrl.com/3.7/examples/js_evaluate.html) [Loading animation](https://pywebview.flowrl.com/3.7/examples/loading_animation.html) → --- # Minimum window size | pywebview [#](https://pywebview.flowrl.com/3.7/examples/min_size#minimum-window-size) Minimum window size ================================================================================================ Set minimum window dimensions. import webview if __name__ == '__main__': # Create a resizable webview window with minimum size constraints webview.create_window('Minimum window size', 'https://pywebview.flowrl.com/hello', min_size=(400, 200)) webview.start() ← [Localization](https://pywebview.flowrl.com/3.7/examples/localization.html) [Minimize / restore window](https://pywebview.flowrl.com/3.7/examples/minimize_window.html) → --- # Link types | pywebview [#](https://pywebview.flowrl.com/3.7/examples/links#link-types) Link types =========================================================================== Demonstrate a difference between different link types import webview html = """

Links

Regular links are opened in the application window.

target='_blank' links are opened in an external browser.

""" if __name__ == '__main__': window = webview.create_window('Link types', html=html) webview.start() ← [Loading animation](https://pywebview.flowrl.com/3.7/examples/loading_animation.html) [Localization](https://pywebview.flowrl.com/3.7/examples/localization.html) → --- # Minimize / restore window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/minimize_window#minimize-restore-window) Minimize / restore window ================================================================================================================= Minimize and restore window programmatically import webview from time import sleep def minimize(window): print('Window is started minimized') sleep(5) print('Restoring window') window.restore() sleep(5) print('Minimizing window') window.minimize() if __name__ == '__main__': window = webview.create_window('Minimize window example', html='

Minimize window

', minimized=True) webview.start(minimize, window) ← [Minimum window size](https://pywebview.flowrl.com/3.7/examples/min_size.html) [Move window](https://pywebview.flowrl.com/3.7/examples/move_window.html) → --- # Multi-window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/multiple_windows#multi-window) Multi-window ========================================================================================== Create multiple windows. import webview def third_window(): # Create a new window after the loop started third_window = webview.create_window('Window #3', html='

Third Window

') if __name__ == '__main__': # Master window master_window = webview.create_window('Window #1', html='

First window

') child_window = webview.create_window('Window #2', html='

Second window

') webview.start(third_window) ← [Move window](https://pywebview.flowrl.com/3.7/examples/move_window.html) [Open file dialog](https://pywebview.flowrl.com/3.7/examples/open_file_dialog.html) → --- # Resize window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/resize_window#resize-window) Resize window ========================================================================================= def resize(window): print('Window size is ({0}, {1})'.format(window.width, window.height)) sleep(2) window.resize(420, 420) print('Window size is ({0}, {1})'.format(window.width, window.height)) if __name__ == '__main__': window = webview.create_window('Resize window example', html='

Resize window

', width=800, height=600) webview.start(resize, window) ← [Open URL](https://pywebview.flowrl.com/3.7/examples/open_url.html) [Save file dialog](https://pywebview.flowrl.com/3.7/examples/save_file_dialog.html) → --- # Open file dialog | pywebview [#](https://pywebview.flowrl.com/3.7/examples/open_file_dialog#open-file-dialog) Open file dialog ================================================================================================== Create an open file dialog after page content is loaded. import webview def open_file_dialog(window): file_types = ('Image Files (*.bmp;*.jpg;*.gif)', 'All files (*.*)') result = window.create_file_dialog(webview.OPEN_DIALOG, allow_multiple=True, file_types=file_types) print(result) if __name__ == '__main__': window = webview.create_window('Open file dialog example', 'https://pywebview.flowrl.com/hello') webview.start(open_file_dialog, window) ← [Multi-window](https://pywebview.flowrl.com/3.7/examples/multiple_windows.html) [Open URL](https://pywebview.flowrl.com/3.7/examples/open_url.html) → --- # Toggle full-screen | pywebview [#](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen#toggle-full-screen) Toggle full-screen ======================================================================================================= Switch application window to a full-screen mode after five seconds. import webview import time def toggle_fullscreen(window): # wait a few seconds before toggle fullscreen: time.sleep(5) window.toggle_fullscreen() if __name__ == '__main__': window = webview.create_window('Full-screen window', 'https://pywebview.flowrl.com/hello') webview.start(toggle_fullscreen, window) ← [Screens](https://pywebview.flowrl.com/3.7/examples/screens.html) [Change user agent string](https://pywebview.flowrl.com/3.7/examples/user_agent.html) → --- # Open URL | pywebview [#](https://pywebview.flowrl.com/3.7/examples/open_url#open-url) Open URL ========================================================================== import webview if __name__ == '__main__': # Create a standard webview window window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/hello') webview.start() ← [Open file dialog](https://pywebview.flowrl.com/3.7/examples/open_file_dialog.html) [Resize window](https://pywebview.flowrl.com/3.7/examples/resize_window.html) → --- # Donating | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/donating#donating) Donating ============================================================================== [#](https://pywebview.flowrl.com/3.7/contributing/donating#recurrring-pledge) Recurrring pledge ------------------------------------------------------------------------------------------------ Recurring pledges come perks, like getting email support or featuring your name or logo in the project repository [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [#](https://pywebview.flowrl.com/3.7/contributing/donating#one-time-donations) One-time donations -------------------------------------------------------------------------------------------------- We accept donations via Paypal [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) ← [Bug reporting](https://pywebview.flowrl.com/3.7/contributing/bug_reporting.html) [Documentation](https://pywebview.flowrl.com/3.7/contributing/documentation.html) → --- # Development | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/development#development) Development ======================================================================================= Before you get busy coding a new feature, create an issue and discuss the details in the issue tracker. [#](https://pywebview.flowrl.com/3.7/contributing/development#environment-set-up) Environment set-up ----------------------------------------------------------------------------------------------------- This guide assumes you have a [GitHub (opens new window)](https://github.com/) account, as well as [Python 3 (opens new window)](https://python.org/) , [virtualenv (opens new window)](https://virtualenv.pypa.io/en/stable/) and [Git (opens new window)](https://git-scm.com/) installed. The guide is written for Bash, for Windows you can use for example Bash bundled with Git. * [Fork (opens new window)](https://github.com/r0x0r/pywebview/fork) _pywebview_ * Clone your forked repository git clone https://github.com//pywebview cd pywebview * Create a virtual environment virtualenv -p python3 venv source venv/bin/activate pip install -e . pip install pytest * Hello world python examples/simple_browser.py [#](https://pywebview.flowrl.com/3.7/contributing/development#development-work-flow) Development work-flow ----------------------------------------------------------------------------------------------------------- * Create and checkout a new branch git checkout -b new-branch master * Make your changes * Run tests pytest tests * Commit and push your work git add . git commit -m "Your commit message goes here" git push -u origin new-branch * [Create a pull request (opens new window)](https://help.github.com/articles/creating-a-pull-request/) [#](https://pywebview.flowrl.com/3.7/contributing/development#testing) Testing ------------------------------------------------------------------------------- pywebview uses [pytest (opens new window)](https://docs.pytest.org/en/latest/) for testing. To run all the tests in the project root directory pytest tests To run a specific test pytest tests/test_simple_browser.py Tests cover only trivial mistakes, syntax errors, exceptions and such. In other words there is no functional testing. Each test verifies that a pywebview window can be opened and exited without errors when run under different scenarios. Sometimes test fail / stuck randomly. The cause of the issue is not known, any help on resolving random fails is greatly appreciated. [#](https://pywebview.flowrl.com/3.7/contributing/development#learning) Learning --------------------------------------------------------------------------------- ### [#](https://pywebview.flowrl.com/3.7/contributing/development#windows) Windows * [Windows Forms documentation (opens new window)](https://docs.microsoft.com/en-us/dotnet/framework/winforms/) * [Windows Forms API (opens new window)](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms) ### [#](https://pywebview.flowrl.com/3.7/contributing/development#macos) macOS * [pyobjc (opens new window)](https://pythonhosted.org/pyobjc/) . Converting Objective C syntax to Python can be tricky at first. Be sure to check out the [pyobjc intro (opens new window)](https://pythonhosted.org/pyobjc/core/intro.html) . * [AppKit (opens new window)](https://developer.apple.com/documentation/appkit) * [WebKit (opens new window)](https://developer.apple.com/documentation/webkit) ### [#](https://pywebview.flowrl.com/3.7/contributing/development#linux) Linux * [PyGObject API reference (opens new window)](https://lazka.github.io/pgi-docs/) ### [#](https://pywebview.flowrl.com/3.7/contributing/development#qt) Qt * [Qt for Python Documentation (opens new window)](https://doc.qt.io/qtforpython-5/contents.html) * [Qt5 documentation (opens new window)](https://doc.qt.io/qt-5/index.html) * [PySide2 QtWidgets (opens new window)](https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/index.html) [Bug reporting](https://pywebview.flowrl.com/3.7/contributing/bug_reporting.html) → --- # pywebview ![pywebview 3.0](https://pywebview.flowrl.com/3.7/assets/img/pywebview3.5e63e895.png) [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#introducing-pywebview-3-0) Introducing pywebview 3.0 ========================================================================================================== I am happy to announce the release of _pywebview 3.0_. _pywebview_ lets you to build GUI for your Python program using HTML, CSS and Javascript, while doing its best hiding the fact that the GUI is built using a browser. Think of _pywebview_ as lightweight Electron for Python. Unlike Electron, _pywebview_ does not bundle a web renderer, but instead relies on a rendered provided by operating system. _Sidenote: bundling a renderer is still an option though, as in case of CEF_. If you are new here, head over to [usage guide](https://pywebview.flowrl.com/3.7/guide/usage.html) , [API reference](https://pywebview.flowrl.com/3.7/guide/api.html) , [examples](https://pywebview.flowrl.com/examples) and our very own [TODOs app (opens new window)](https://github.com/r0x0r/pywebview/tree/master/examples/todos) . Oh and _pywebview_ can be installed with pip install pywebview [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#what-s-new) What's new? ----------------------------------------------------------------------------- Version 3.0 is the first version that is not compatible with previous versions. Multi-window support introduced in 2.x resulted in some questionable architectural decisions, which now have been resolved and hopefully make more sense. Notable changes include: ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#webview-start) webview.start() The biggest change is introduction of window objects and `webview.start()` function that starts a GUI loop. Previously GUI loop was started by the first call of `webview.create_window()`. Hence `create_window` had in fact two functions: creating a window and starting a GUI loop. To make things more confusing the first call to `create_window` was blocking, while subsequent calls from subthreads were not. To make things more straightforward, `create_window` now creates a window and returns a window object, no matter how many times you call it. The function is always non-blocking too. Bear in mind that until GUI loop is started, no windows are displayed. Using new API, hello world in _pywebview_ looks like this: import webview window = webview.create_window('Hello world', 'https://pywebview.flowrl.com/hello') webview.start() `webview.start` also provides a convenient way to execute thread specific code after GUI loop is started, so no more threading boilerplate. import webview def change_title(window): window.change_title('pywebview whoa') window = webview.create_window('pywebview wow', 'https://pywebview.flowrl.com/hello') webview.start(change_title, window) ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#window-object) Window object All the functions related to window management and web content have been moved to a window object as returned by `webview.create_window`. For example `webview.load_html` became `window.load_html` as in: import webview def load_html(window): window.load_html('

pywebview wow!

') window = webview.create_window('pywebview wow') webview.start(load_html, window) ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#built-in-http-server) Built-in HTTP server _pywebview_ now provides its own HTTP server for serving static local files. For obfuscation purposes server is started on a random port. import webview window = webview.create_window('pywebview wow', 'assets/index.html') webview.start(http_server=True) ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#events) Events 3.0 introduces a new event system that lets to subscribe/unsubscribe to events. Currently `shown` and `loaded` events are implemented. Event objects are provided by a window object. See [events example](https://pywebview.flowrl.com/3.7/examples/events.html) for usage details. ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#edge-support) Edge support Windows now provides support for EdgeHTML. EdgeHTML is automatically chosen if your system requirements are met (.NET 4.6.2 and Windows 10 1803). Unfortunately accessing local files is not currently possible with EdgeHTML, so you must use a HTTP server. If you wish for some reason to force MSHTML, you can `webview.start(gui='mshtml')`. ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#create-window-now-can-load-html-directly) create\_window now can load html directly import webview window = webview.create_window('pywebview wow', html='

pywebview wow!

') webview.start() If both url and html parameters are provided, html takes precedence. ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#get-elements) get\_elements You can now retrieve DOM nodes by using `window.get_elements(selector)` function. Nodes are serialized using [domJSON (opens new window)](https://github.com/azaslavsky/domJSON) library. [Example](https://pywebview.flowrl.com/3.7/examples/get_elements.html) ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#config-is-gone) Config is gone `webview.config` is no more. To set a GUI renderer, use the `gui` parameter to `webview.start` ### [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#confirm-quit-is-now-confirm-close) confirm\_quit is now confirm\_close E.g. `webview.create_window('Window', confirm_close=True)` [#](https://pywebview.flowrl.com/3.7/blog/pywebview3#support-the-project) Support the project ============================================================================================== _pywebview_ is a small project with limited resources, any help is welcome. PRs, documentation, research, anything goes. Having said that commits are preferred over comments. Check out the [contributing guide](https://pywebview.flowrl.com/contributing) to get started. If you find _pywebview_ useful, please support it. We offer donations via Patreon and Open Collective, as well as one-time Paypal donations. If you represent a company, consider becoming a sponsor to get exposure for your company and connect with Python developers. [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) --- # Save file dialog | pywebview [#](https://pywebview.flowrl.com/3.7/examples/save_file_dialog#save-file-dialog) Save file dialog ================================================================================================== Create a save file dialog after page content is loaded. import webview import time def save_file_dialog(window): time.sleep(5) result = window.create_file_dialog(webview.SAVE_DIALOG, directory='/', save_filename='test.file') print(result) if __name__ == '__main__': window = webview.create_window('Save file dialog', 'https://pywebview.flowrl.com/hello') webview.start(save_file_dialog, window) ← [Resize window](https://pywebview.flowrl.com/3.7/examples/resize_window.html) [Screens](https://pywebview.flowrl.com/3.7/examples/screens.html) → --- # Bug reporting | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/bug_reporting#bug-reporting) Bug reporting ============================================================================================= If you think you found a bug, verify following steps first 1. Does the bug occur in a default browser? If so, the problem is with your code, not pywebview 2. Are you using the latest master? Bug fixes are merged into the master and it may take a while until a new release is deployed to Pypi. 3. Has it been [reported (opens new window)](https://github.com/r0x0r/pywebview/issues) already? If you verified all the three points and are sure that the issue is caused by pywebview, feel free to submit a new issue. Please remember to specify under which operating system the bug occurs, as well as with other relevant information. In case of Linux, specify a distro you are using. ← [Development](https://pywebview.flowrl.com/3.7/contributing/development.html) [Donating](https://pywebview.flowrl.com/3.7/contributing/donating.html) → --- # Change user agent string | pywebview [#](https://pywebview.flowrl.com/3.7/examples/user_agent#change-user-agent-string) Change user agent string ============================================================================================================ Change the user-agent of a window. EdgeHTML is not supported. import webview if __name__ == '__main__': webview.create_window('User Agent Test', 'https://pywebview.flowrl.com/hello') webview.start(user_agent='Custom user agent') ← [Toggle full-screen](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen.html) [Window title change](https://pywebview.flowrl.com/3.7/examples/window_title_change.html) → --- # Window title change | pywebview [#](https://pywebview.flowrl.com/3.7/examples/window_title_change#window-title-change) Window title change =========================================================================================================== Change window title every three seconds. import webview import time def change_title(window): """changes title every 3 seconds""" for i in range(1, 100): time.sleep(3) window.set_title('New Title #{}'.format(i)) if __name__ == '__main__': window = webview.create_window('Change title example', 'https://pywebview.flowrl.com/hello') webview.start(change_title, window) ← [Change user agent string](https://pywebview.flowrl.com/3.7/examples/user_agent.html) --- # Screens | pywebview [#](https://pywebview.flowrl.com/3.7/examples/screens#screens) Screens ======================================================================= Get available display information using `webview.screens` import webview def display_screen_info(): screens = webview.screens print('Available screens are: ' + str(screens)) if __name__ == '__main__': display_screen_info() # display screen info before starting app window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/hello') webview.start(display_screen_info) ← [Save file dialog](https://pywebview.flowrl.com/3.7/examples/save_file_dialog.html) [Toggle full-screen](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen.html) → --- # Debugging | pywebview [#](https://pywebview.flowrl.com/3.7/guide/debugging#debugging) Debugging ========================================================================== To debug Javascript, set the `debug` parameter of `start` to `True` import webview webview.create_window('https://pywebview.flowrl.com/hello') webview.start(debug=True) This will enable web inspector on macOS, GTK and QT (QTWebEngine only). To open the web inspector, right click on the page and select Inspect. To debug EdgeHTML, you need to install [Microsoft Edge DevTools Preview (opens new window)](https://www.microsoft.com/en-us/p/microsoft-edge-devtools-preview/9mzbfrmz0mnj) . Launch the application and select your application from the list of running WebViews. The `debug` flag also routes `console.logs` to the Python console. There is no way to attach an external debugger to MSHTML. The `debug` flag enables Javascript error reporting and right-click context menu on Windows. ← [Application architecture](https://pywebview.flowrl.com/3.7/guide/architecture.html) [Interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) → --- # Freezing | pywebview [#](https://pywebview.flowrl.com/3.7/guide/freezing#freezing) Freezing ======================================================================= [#](https://pywebview.flowrl.com/3.7/guide/freezing#macos) macOS ----------------------------------------------------------------- Use [py2app (opens new window)](https://py2app.readthedocs.io/en/latest/) . For a reference setup.py for py2app, look [here (opens new window)](https://github.com/r0x0r/pywebview/blob/master/examples/py2app_setup.py) . [#](https://pywebview.flowrl.com/3.7/guide/freezing#windows) Windows --------------------------------------------------------------------- Use [pyinstaller (opens new window)](https://www.pyinstaller.org/) . If you are using _PyInstaller>=3.6_, it should work out of the box as there is hook that takes care of the bundling of necessary dlls. Therefore, this version of PyInstaller is the recommended one. Should you need to use prior versions of PyInstaller (<=3.5), you will need to bundle the dlls yourself. Either [WebBrowserInterop.x86.dll (opens new window)](https://github.com/r0x0r/pywebview/blob/master/webview/lib/WebBrowserInterop.x86.dll) or [WebBrowserInterop.x64.dll (opens new window)](https://github.com/r0x0r/pywebview/blob/master/webview/lib/WebBrowserInterop.x64.dll) depending on whether you build against 32-bit or 64-bit Python. The DLLs bundled with _pywebview_ and are located in the `site-packages/webview/lib` directory. [#](https://pywebview.flowrl.com/3.7/guide/freezing#linux) Linux ----------------------------------------------------------------- Use [pyinstaller (opens new window)](https://www.pyinstaller.org/) . ← [Interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) [Security](https://pywebview.flowrl.com/3.7/guide/security.html) → --- # Installation | pywebview [#](https://pywebview.flowrl.com/3.7/guide/installation#installation) Installation =================================================================================== pip install pywebview This will install _pywebview_ with default dependencies. To install _pywebview_ with PySide2 (available on Linux and macOS and Windows) use pip install pywebview[qt] To install _pywebview_ with CEF (available on Windows) use pip install pywebview[cef] [#](https://pywebview.flowrl.com/3.7/guide/installation#dependencies) Dependencies ----------------------------------------------------------------------------------- ### [#](https://pywebview.flowrl.com/3.7/guide/installation#windows) Windows [pythonnet (opens new window)](https://github.com/pythonnet/pythonnet) (requires > .NET 4.0) To use with the latest Chromium you need [WebView2 Runtime (opens new window)](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . If you plan to distribute your software, check out [distribution guidelines (opens new window)](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) too. To use with CEF you need [cefpython (opens new window)](https://github.com/cztomczak/cefpython/) pip install cefpython3 ### [#](https://pywebview.flowrl.com/3.7/guide/installation#macos) macOS [pyobjc (opens new window)](https://pythonhosted.org/pyobjc/) `PyObjC` comes presintalled with the Python bundled in macOS. For a stand-alone Python installation you have to install it separately. You can also use QT5 in macOS ### [#](https://pywebview.flowrl.com/3.7/guide/installation#linux) Linux `pip install pywebview[qt]` should take of QT dependencies. If it does not work or you would like to use GTK, you may try these recipes. [PyGObject (opens new window)](https://pygobject.readthedocs.io/en/latest/) is used with GTK. To install dependencies on Ubuntu for both Python 3 and 2 sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-webkit2-4.0 For other distributions, consult the [PyGObject documentation (opens new window)](https://pygobject.readthedocs.io/en/latest/getting_started.html) Note that WebKit2 version 2.22 or greater is required for certain features to work correctly. If your distribution ships with an older version, you may need to install it manually from a backport. [PySide2 (opens new window)](https://doc.qt.io/qtforpython-5/) is used with QT. `pywebview` supports both QtWebChannel (newer and preferred) and QtWebKit implementations. Use QtWebChannel, unless it is not available on your system. To install QT via pip pip install qtpy pyside2 To install QtWebChannel on Debian-based systems (more modern, preferred) sudo apt install python3-pyqt5 python3-pyqt5.qtwebengine python3-pyqt5.qtwebchannel libqt5webkit5-dev To install QtWebKit (legacy, but available for more platforms). sudo apt install python3-pyqt5 python3-pyqt5.qtwebkit python-pyqt5 python-pyqt5.qtwebkit libqt5webkit5-dev WARNING Starting from Ubuntu Disco Dingo _pywebview_ can be installed via `apt` on Debian based system as `python-pywebview`. This package features an old version of _pywebview_ that is API incompatible with the current version. If you choose to install it, you can find documentation [here](https://pywebview.flowrl.com/2.4) [Usage](https://pywebview.flowrl.com/3.7/guide/usage.html) → --- # Usage | pywebview [#](https://pywebview.flowrl.com/3.7/guide/usage#usage) Usage ============================================================== [#](https://pywebview.flowrl.com/3.7/guide/usage#basics) Basics ---------------------------------------------------------------- The bare minimum to get _pywebview_ up and running is import webview window = webview.create_window('Woah dude!', 'https://pywebview.flowrl.com') webview.start() The `create_window` function returns a window instance that provides a number of both window manipulation and DOM related functions. You may create as many windows as you wish. Windows created after the GUI loop is started are shown immediately. All the opened windows are stored as a list in `webview.windows`. The windows are stored in a creation order. The `create_window` second argument `url` can point to a remote or a local path. Alternatively, you can load HTML by setting the `html` parameter. import webview webview.create_window('Woah dude!', html='

Woah dude!

') webview.start() Note that if both `url` and `html` are set, `html` takes precedence. _pywebview_ gives a choice of several web renderers. To change a web renderer, set the `gui` parameter of the `start` function to the desired value (e.g `cef` or `qt`). See [Renderer](https://pywebview.flowrl.com/3.7/guide/renderer.html) for details. [#](https://pywebview.flowrl.com/3.7/guide/usage#http-server) HTTP server -------------------------------------------------------------------------- _pywebview_ provides a WSGI-compatible HTTP server. To start a HTTP server set the url to a local entry point (without a protocol schema) and set the `http_server` parameter of the `start` function to `True` import webview webview.create_window('Woah dude!', 'index.html') webview.start(http_server=True) If you wish to use an external WSGI compatible HTTP server with _pywebview_, you can pass a server object as an URL, ie. `http_server` parameter does not need to be set in this case. from flask import Flask import webview server = Flask(__name__, static_folder='./assets', template_folder='./templates') webview.create_window('Flask example', server) webview.start() [#](https://pywebview.flowrl.com/3.7/guide/usage#threading-model) Threading model ---------------------------------------------------------------------------------- `webview.start` starts a GUI loop and is a blocking function. With the GUI loop being blocking, you must execute your backend logic in a separate thread or a process. You may launch a thread or a process manually. Alternatively you can execute your code by passing your function as the first parameter `func` to `start`. The second parameter sets the function's arguments. This approach starts a thread behind the scenes and is identical to starting a thread manually. import webview def custom_logic(window): window.toggle_fullscreen() window.evaluate_js('alert("Nice one brother")') window = webview.create_window('Woah dude!', html='

Woah dude!

') webview.start(custom_logic, window) # anything below this line will be executed after program is finished executing pass [#](https://pywebview.flowrl.com/3.7/guide/usage#make-python-and-javascript-talk-with-each-other) Make Python and Javascript talk with each other ================================================================================================================================================== You can think of custom logic as a backend that communicates with frontend code in the HTML/JS realm. Now how would you make two to communicate with each other? _pywebview_ offers a two way JS-Python bridge that lets you both execute Javascript from Python (via `evaluate_js`) and Python code from Javascript (via `js_api` and `expose`). See [interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) for details. Another way is to run a Python web server (like Flask or Bottle) in custom logic and make frontend code make API calls to it. That would be identical to a typical web application. This approach is suitable, for example, for porting an existing web application to a desktop application. See [Architecture](https://pywebview.flowrl.com/3.7/guide/architecture.html) for more information on both approaches. ← [Installation](https://pywebview.flowrl.com/3.7/guide/installation.html) [API](https://pywebview.flowrl.com/3.7/guide/api.html) → --- # Interdomain communication | pywebview [#](https://pywebview.flowrl.com/3.7/guide/interdomain#interdomain-communication) Interdomain communication ============================================================================================================ [#](https://pywebview.flowrl.com/3.7/guide/interdomain#invoke-javascript-from-python) Invoke Javascript from Python -------------------------------------------------------------------------------------------------------------------- `window.evaluate_js(code, callback=None)` allows you to execute arbitrary Javascript code with a last value returned synchronously. If callback function is supplied, then promises are resolved and the callback function is called with the result as a parameter. Javascript types are converted to Python types, eg. JS objects to dicts, arrays to lists, undefined to None. Note that due implementation limitations the string 'null' will be evaluated to None. You must escape \\n and \\r among other escape sequences if they present in Javascript code. Otherwise they get parsed by Python. r'strings' is a recommended way to load Javascript. For GTK WebKit2 versions older than 2.22, there is a limit of about ~900 characters for a value returned by `evaluate_js`. [#](https://pywebview.flowrl.com/3.7/guide/interdomain#invoke-python-from-javascript) Invoke Python from Javascript -------------------------------------------------------------------------------------------------------------------- Invoking Python functions from Javascript can be done with two different approaches. * by exposing an instance of a Python class to the `js_api` of `create_window`. All the callable methods of the class will be exposed to the JS domain as `pywebview.api.method_name` with correct parameter signatures. Method name must not start with an underscore. See an [example](https://pywebview.flowrl.com/3.7/examples/js_api.html) . * by passing your function(s) to window object's `expose(func)`. This will expose a function or functions to the JS domain as `pywebview.api.func_name`. Unlike JS API, `expose` allows to expose functions also at the runtime. If there is a name clash between JS API and functions exposed this way, the latter takes precedence. See an [example](https://pywebview.flowrl.com/3.7/examples/expose.html) . Exposed function returns a promise that is resolved to its result value. Exceptions are rejected and encapsulated inside a Javascript `Error` object. Stacktrace is available via `error.stack`. Functions are executed in separate threads and are not thread-safe. `window.pywebview.api` is not guaranteed to be available on `window.onload`. Subscribe to `window.pywebviewready` instead to make sure that `window.pywebview.api` is ready. [Example](https://pywebview.flowrl.com/3.7/examples/js_api.html) . ← [Debugging](https://pywebview.flowrl.com/3.7/guide/debugging.html) [Freezing](https://pywebview.flowrl.com/3.7/guide/freezing.html) → --- # Hide / show window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/hide_window#hide-show-window) Hide / show window =============================================================================================== Programmatically hide and show window import webview import time def hide_show(window): time.sleep(5) window.hide() time.sleep(5) window.show() if __name__ == '__main__': window = webview.create_window('Hide / show window', 'https://pywebview.flowrl.com/hello') webview.start(hide_show, window) ← [Get current URL](https://pywebview.flowrl.com/3.7/examples/get_current_url.html) [HTML load](https://pywebview.flowrl.com/3.7/examples/html_load.html) → --- # Move window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/move_window#move-window) Move window =================================================================================== Set window coordinates and move window after its creation. import webview from time import sleep def move(window): print('Window coordinates are ({0}, {1})'.format(window.x, window.y)) sleep(2) window.move(200, 200) print('Window coordinates are ({0}, {1})'.format(window.x, window.y)) if __name__ == '__main__': window = webview.create_window('Move window example', html='

Move window

', x=100, y=100) webview.start(move, window) ← [Minimize / restore window](https://pywebview.flowrl.com/3.7/examples/minimize_window.html) [Multi-window](https://pywebview.flowrl.com/3.7/examples/multiple_windows.html) → --- # Frameless window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/frameless#frameless-window) Frameless window =========================================================================================== Create a frameless window. The window can be moved around by dragging any point. import webview if __name__ == '__main__': webview.create_window('Frameless window', 'http://pywebview.flowrl.com/hello', frameless=True) webview.start() ← [Events](https://pywebview.flowrl.com/3.7/examples/events.html) [Fullscreen window](https://pywebview.flowrl.com/3.7/examples/fullscreen.html) → --- # Fullscreen window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/fullscreen#fullscreen-window) Fullscreen window ============================================================================================== Create a fullscreen window. import webview if __name__ == '__main__': webview.create_window('Full-screen window', 'https://pywebview.flowrl.com/hello', fullscreen=True) webview.start() ← [Frameless window](https://pywebview.flowrl.com/3.7/examples/frameless.html) [Get DOM elements](https://pywebview.flowrl.com/3.7/examples/get_elements.html) → --- # Get current URL | pywebview [#](https://pywebview.flowrl.com/3.7/examples/get_current_url#get-current-url) Get current URL =============================================================================================== Print current URL after page is loaded. import webview def get_current_url(window): print(window.get_current_url()) if __name__ == '__main__': window = webview.create_window('Get current URL', 'https://pywebview.flowrl.com/hello') webview.start(get_current_url, window) ← [Get DOM elements](https://pywebview.flowrl.com/3.7/examples/get_elements.html) [Hide / show window](https://pywebview.flowrl.com/3.7/examples/hide_window.html) → --- # Get DOM elements | pywebview [#](https://pywebview.flowrl.com/3.7/examples/get_elements#get-dom-elements) Get DOM elements ============================================================================================== Get DOM elements using a selector. import webview """ This example demonstrates how to retrieve a DOM element """ def get_elements(window): heading = window.get_elements('#heading') content = window.get_elements('.content') print('Heading:\n %s ' % heading[0]['outerHTML']) print('Content 1:\n %s ' % content[0]['outerHTML']) print('Content 2:\n %s ' % content[1]['outerHTML']) if __name__ == '__main__': html = """

Heading

Content 1
Content 2
""" window = webview.create_window('Get elements example', html=html) webview.start(get_elements, window) ← [Fullscreen window](https://pywebview.flowrl.com/3.7/examples/fullscreen.html) [Get current URL](https://pywebview.flowrl.com/3.7/examples/get_current_url.html) → --- # Quit confirmation dialog | pywebview [#](https://pywebview.flowrl.com/3.7/examples/close_confirm#quit-confirmation-dialog) Quit confirmation dialog =============================================================================================================== import webview """ This example demonstrates a webview window with a quit confirmation dialog. """ if __name__ == '__main__': # Create a standard webview window webview.create_window('Confirm Close Example', 'https://pywebview.flowrl.com/hello', confirm_close=True) webview.start() ← [CSS load](https://pywebview.flowrl.com/3.7/examples/css_load.html) [Debugging](https://pywebview.flowrl.com/3.7/examples/debug.html) → --- # CEF support | pywebview [#](https://pywebview.flowrl.com/3.7/examples/cef#cef-support) CEF support =========================================================================== To use Chrome Embedded Framework on Windows. import webview # To pass custom settings to CEF, import and update settings dict # See the complete set of options for CEF, here: https://github.com/cztomczak/cefpython/blob/master/api/ApplicationSettings.md from webview.platforms.cef import settings, browser_settings settings.update({ 'persist_session_cookies': True }) browser_settings.update({ 'dom_paste_disabled': False }) if __name__ == '__main__': webview.create_window('CEF Example', 'https://pywebview.flowrl.com/hello') webview.start(gui='cef') [Change URL](https://pywebview.flowrl.com/3.7/examples/change_url.html) → --- # Change URL | pywebview [#](https://pywebview.flowrl.com/3.7/examples/change_url#change-url) Change URL ================================================================================ Change URL ten seconds after the first URL is loaded. import webview import time def change_url(window): # wait a few seconds before changing url: time.sleep(10) # change url: window.load_url('https://woot.fi') if __name__ == '__main__': window = webview.create_window('URL Change Example', 'https://pywebview.flowrl.com/hello') webview.start(change_url, window) ← [CEF support](https://pywebview.flowrl.com/3.7/examples/cef.html) [CSS load](https://pywebview.flowrl.com/3.7/examples/css_load.html) → --- # API | pywebview [#](https://pywebview.flowrl.com/3.7/guide/api#api) API ======================================================== [#](https://pywebview.flowrl.com/3.7/guide/api#webview-create-window) webview.create\_window --------------------------------------------------------------------------------------------- webview.create_window(title, url='', html='', js_api=None, width=800, height=600, \ x=None, y=None, resizable=True, fullscreen=False, \ min_size=(200, 100), hidden=False, frameless=False, \ minimized=False, on_top=False, confirm_close=False, \ background_color='#FFF', text_select=False) Create a new _pywebview_ window and returns its instance. Window is not shown until the GUI loop is started. If the function is invoked during the GUI loop, the window is displayed immediately. * `title` - Window title * `url` - URL to load. If the URL does not have a protocol prefix, it is resolved as a path relative to the application entry point. Alternatively a WSGI server object can be passed to start a local web server. * `html` - HTML code to load. If both URL and HTML are specified, HTML takes precedence. * `js_api` - Expose a python object to the DOM of the current `pywebview` window. Methods of the `js_api` object can be executed from Javascript by calling `window.pywebview.api.()`. Please note that the calling Javascript function receives a promise that will contain the return value of the python function. Only basic Python objects (like int, str, dict, ...) can be returned to Javascript. * `width` - Window width. Default is 800px. * `height` - Window height. Default is 600px. * `x` - Window x coordinate. Default is centered. * `y` - Window y coordinate. Default is centered. * `resizable` - Whether window can be resized. Default is True * `fullscreen` - Start in fullscreen mode. Default is False * `min_size` - a (width, height) tuple that specifies a minimum window size. Default is 200x100 * `hidden` - Create a window hidden by default. Default is False * `frameless` - Create a frameless window. Default is False. * `easy_drag` - Easy drag mode for frameless windows. Window can be moved by dragging any point. Default is True. Note that easy\_drag has no effect with normal windows. To control dragging on an element basis, see [drag area](https://pywebview.flowrl.com/3.7/guide/api.html#drag-area) for details. * `minimized` - Start in minimized mode * `on_top` - Set window to be always on top of other windows. Default is False. * `confirm_close` - Whether to display a window close confirmation dialog. Default is False * `background_color` - Background color of the window displayed before WebView is loaded. Specified as a hex color. Default is white. * `transparent` - Create a transparent window. Not supported on Windows. Default is False. Note that this setting does not hide or make window chrome transparent. To hide window chrome set `frameless` to True. * `text_select` - Enables document text selection. Default is False. To control text selection on per element basis, use [user-select (opens new window)](https://developer.mozilla.org/en-US/docs/Web/CSS/user-select) CSS property. [#](https://pywebview.flowrl.com/3.7/guide/api#webview-start) webview.start ---------------------------------------------------------------------------- webview.start(func=None, args=None, localization={}, gui=None, debug=False, \ http_server=False, user_agent=None) Start a GUI loop and display previously created windows. This function must be called from a main thread. * `func` - function to invoke upon starting the GUI loop. * `args` - function arguments. Can be either a single value or a tuple of values. * `localization` - a dictionary with localized strings. Default strings and their keys are defined in localization.py * `gui` - force a specific GUI. Allowed values are `cef`, `qt` or `gtk` depending on a platform. See [Renderer](https://pywebview.flowrl.com/3.7/guide/renderer.html) for details. * `debug` - enable debug mode. See [Debugging](https://pywebview.flowrl.com/3.7/guide/debugging.html) for details. * `http_server` - enable built-in HTTP server. If enabled, local files will be served using a local HTTP server on a random port. For each window, a separate HTTP server is spawned. This option is ignored for non-local URLs. * `user_agent` - change user agent string. Not supported in EdgeHTML. ### [#](https://pywebview.flowrl.com/3.7/guide/api#examples) Examples * [Simple window](https://pywebview.flowrl.com/3.7/examples/open_url.html) * [Multi-window](https://pywebview.flowrl.com/3.7/examples/multiple_windows.html) [#](https://pywebview.flowrl.com/3.7/guide/api#webview-screens) webview.screens -------------------------------------------------------------------------------- webview.screens Return a list of available displays (as `Screen` objects) with the primary display as the first element of the list. ### [#](https://pywebview.flowrl.com/3.7/guide/api#examples-2) Examples * [Simple window](https://pywebview.flowrl.com/3.7/examples/screens.html) [#](https://pywebview.flowrl.com/3.7/guide/api#webview-token) webview.token ---------------------------------------------------------------------------- webview.token A CSRF token property unique to the session. The same token is exposed as `window.pywebview.token`. See [Security](https://pywebview.flowrl.com/3.7/guide/security.html) for usage details. [#](https://pywebview.flowrl.com/3.7/guide/api#screen-object) Screen object ============================================================================ Represents a display found on the system. [#](https://pywebview.flowrl.com/3.7/guide/api#height) height -------------------------------------------------------------- screen.height Get display height. [#](https://pywebview.flowrl.com/3.7/guide/api#width) width ------------------------------------------------------------ screen.width Get display width. [#](https://pywebview.flowrl.com/3.7/guide/api#window-object) Window object ============================================================================ Represents a window that hosts webview. `window` object is returned by `create_window` function. [#](https://pywebview.flowrl.com/3.7/guide/api#on-top) on\_top --------------------------------------------------------------- window.on_top Get or set whether the window is always on top [#](https://pywebview.flowrl.com/3.7/guide/api#x) x ---------------------------------------------------- window.x Get X coordinate of the top-left corrner of the window [#](https://pywebview.flowrl.com/3.7/guide/api#y) y ---------------------------------------------------- window.y Get Y coordinate of the top-left corrner of the window [#](https://pywebview.flowrl.com/3.7/guide/api#width-2) width -------------------------------------------------------------- window.width Get width of the window [#](https://pywebview.flowrl.com/3.7/guide/api#height-2) height ---------------------------------------------------------------- window.height Get height of the window [#](https://pywebview.flowrl.com/3.7/guide/api#create-file-dialog) create\_file\_dialog ---------------------------------------------------------------------------------------- window.create_file_dialog(dialog_type=OPEN_DIALOG, directory='', allow_multiple=False, save_filename='', file_types=())` Create an open file (`webview.OPEN_DIALOG`), open folder (`webview.FOLDER_DIALOG`) or save file (`webview.SAVE_DIALOG`) dialog. Return a tuple of selected files, None if cancelled. * `allow_multiple=True` enables multiple selection. * `directory` Initial directory. * `save_filename` Default filename for save file dialog. * `file_types` A tuple of supported file type strings in the open file dialog. A file type string must follow this format `"Description (*.ext1;*.ext2...)"`. If the argument is not specified, then the `"All files (*.*)"` mask is used by default. The 'All files' string can be changed in the localization dictionary. ### [#](https://pywebview.flowrl.com/3.7/guide/api#examples-3) Examples * [Open-file dialog](https://pywebview.flowrl.com/3.7/examples/open_file_dialog.html) * [Save-file dialog](https://pywebview.flowrl.com/3.7/examples/save_file_dialog.html) [#](https://pywebview.flowrl.com/3.7/guide/api#destroy) destroy ---------------------------------------------------------------- window.destroy() Destroy the window. [Example](https://pywebview.flowrl.com/3.7/examples/destroy_window.html) [#](https://pywebview.flowrl.com/3.7/guide/api#evaluate-js) evaluate\_js ------------------------------------------------------------------------- window.evaluate_js(script, callback=None) Execute Javascript code. The last evaluated expression is returned. If callback function is supplied, then promises are resolved and the callback function is called with the result as a parameter. Javascript types are converted to Python types, eg. JS objects to dicts, arrays to lists, undefined to None. Note that due implementation limitations the string 'null' will be evaluated to None. You must escape \\n and \\r among other escape sequences if they present in Javascript code. Otherwise they get parsed by Python. r'strings' is a recommended way to load Javascript. For GTK WebKit2 versions older than 2.22, there is a limit of about ~900 characters for a value returned by `evaluate_js`. [#](https://pywebview.flowrl.com/3.7/guide/api#get-current-url) get\_current\_url ---------------------------------------------------------------------------------- window.get_current_url() Return the current URL. None if no url is loaded. [Example](https://pywebview.flowrl.com/3.7/examples/get_current_url.html) [#](https://pywebview.flowrl.com/3.7/guide/api#get-elements) get\_elements --------------------------------------------------------------------------- window.get_elements(selector) Return the serialized DOM element by its selector. None if no element matches. For GTK you must have WebKit2 2.22 or greater to use this function. [Example](https://pywebview.flowrl.com/3.7/examples/get_elements.html) [#](https://pywebview.flowrl.com/3.7/guide/api#hide) hide ---------------------------------------------------------- window.hide() Hide the window. [Example](https://pywebview.flowrl.com/3.7/examples/show_hide.html) [#](https://pywebview.flowrl.com/3.7/guide/api#load-css) load\_css ------------------------------------------------------------------- window.load_css(css) Load CSS as a string. [Example](https://pywebview.flowrl.com/3.7/examples/css_load.html) [#](https://pywebview.flowrl.com/3.7/guide/api#load-html) load\_html --------------------------------------------------------------------- window.load_html(content, base_uri=base_uri()) Load HTML code. Base URL for resolving relative URLs is set to the directory the program is launched from. Note that you cannot use hashbang anchors when HTML is loaded this way. [Example](https://pywebview.flowrl.com/3.7/examples/html_load.html) [#](https://pywebview.flowrl.com/3.7/guide/api#load-url) load\_url ------------------------------------------------------------------- window.load_url(url) Load a new URL. [Example](https://pywebview.flowrl.com/3.7/examples/change_url.html) [#](https://pywebview.flowrl.com/3.7/guide/api#minimize) minimize ------------------------------------------------------------------ window.minimize() Minimize window. [Example](https://pywebview.flowrl.com/3.7/examples/minimize.html) [#](https://pywebview.flowrl.com/3.7/guide/api#move) move ---------------------------------------------------------- window.move(x, y) Move window to a new position. [Example](https://pywebview.flowrl.com/3.7/examples/move_window.html) [#](https://pywebview.flowrl.com/3.7/guide/api#resize) resize -------------------------------------------------------------- window.resize(width, height, fix_point=FixPoint.NORTH | FixPoint.WEST) Resize window. Optional parameter fix\_point specifies in respect to which point the window is resized. The parameter accepts values of the `webview.window.FixPoint` enum (`NORTH`, `SOUTH`, `EAST`, `WEST`) [Example](https://pywebview.flowrl.com/3.7/examples/minimize.html) [#](https://pywebview.flowrl.com/3.7/guide/api#restore) restore ---------------------------------------------------------------- window.restore() Restore minimized window. [Example](https://pywebview.flowrl.com/3.7/examples/minimize.html) [#](https://pywebview.flowrl.com/3.7/guide/api#set-title) set\_title --------------------------------------------------------------------- window.set_title(title) Change the title of the window. [Example](https://pywebview.flowrl.com/3.7/examples/window_title_change.html) [#](https://pywebview.flowrl.com/3.7/guide/api#show) show ---------------------------------------------------------- window.show() Show the window if it is hidden. Has no effect otherwise [Example](https://pywebview.flowrl.com/3.7/examples/show_hide.html) [#](https://pywebview.flowrl.com/3.7/guide/api#toggle-fullscreen) toggle\_fullscreen ------------------------------------------------------------------------------------- window.toggle_fullscreen() Toggle fullscreen mode on the active monitor. [Example](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen.html) [#](https://pywebview.flowrl.com/3.7/guide/api#events) Events ============================================================== Window object has a number of lifecycle events. To subscribe to an event, use the `+=` syntax, e.g. `window.events.loaded += func`. The func will be invoked, when event is fired. Duplicate subscriptions are ignored and function is invoked only once for duplicate subscribers. To unsubscribe `window.events.loaded -= func`. [#](https://pywebview.flowrl.com/3.7/guide/api#events-closed) events.closed ---------------------------------------------------------------------------- Event fired just before pywebview window is closed. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api#events-closing) events.closing ------------------------------------------------------------------------------ Event fired when pywebview window is about to be closed. If confirm\_quit is set, then this event is fired before the close confirmation is displayed. If event handler returns False, the close operation will be cancelled. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api#events-loaded) events.loaded ---------------------------------------------------------------------------- Event fired when DOM is ready. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api#events-minimized) events.minimized ---------------------------------------------------------------------------------- Event fired when window is minimized. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api#events-restore) events.restore ------------------------------------------------------------------------------ Event fired when window is restored. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api#events-maximized) events.maximized ---------------------------------------------------------------------------------- Event fired when window is maximized (fullscreen on macOS) [#](https://pywebview.flowrl.com/3.7/guide/api#events-resized) events.resized ------------------------------------------------------------------------------ Event fired when pywebview window is resized. Event handler can either have no or accept (width, height) arguments. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api#events-shown) events.shown -------------------------------------------------------------------------- Event fired when pywebview window is shown. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api#dom-events) DOM events ====================================================================== _pywebview_ exposes a `window.pywebviewready` DOM event that is fired when `window.pywebview` is created. [Example](https://pywebview.flowrl.com/3.7/examples/js_api.html) [#](https://pywebview.flowrl.com/3.7/guide/api#drag-area) Drag area ==================================================================== With a frameless _pywebview_ window, A window can be moved or dragged by adding a special class called `pywebview-drag-region` in your html
This div element can be used to moved or drag your window like a native OS window
The magic class name can be overriden by re-assigning the `webview.DRAG_REGION_SELECTOR` constant. [Example](https://pywebview.flowrl.com/3.7/examples/js_api.html) ← [Usage](https://pywebview.flowrl.com/3.7/guide/usage.html) [Application architecture](https://pywebview.flowrl.com/3.7/guide/architecture.html) → --- # CEF support | pywebview [#](https://pywebview.flowrl.com/3.7/examples/cef.html#cef-support) CEF support ================================================================================ To use Chrome Embedded Framework on Windows. import webview # To pass custom settings to CEF, import and update settings dict # See the complete set of options for CEF, here: https://github.com/cztomczak/cefpython/blob/master/api/ApplicationSettings.md from webview.platforms.cef import settings, browser_settings settings.update({ 'persist_session_cookies': True }) browser_settings.update({ 'dom_paste_disabled': False }) if __name__ == '__main__': webview.create_window('CEF Example', 'https://pywebview.flowrl.com/hello') webview.start(gui='cef') [Change URL](https://pywebview.flowrl.com/3.7/examples/change_url.html) → --- # Bug reporting | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/bug_reporting.html#bug-reporting) Bug reporting ================================================================================================== If you think you found a bug, verify following steps first 1. Does the bug occur in a default browser? If so, the problem is with your code, not pywebview 2. Are you using the latest master? Bug fixes are merged into the master and it may take a while until a new release is deployed to Pypi. 3. Has it been [reported (opens new window)](https://github.com/r0x0r/pywebview/issues) already? If you verified all the three points and are sure that the issue is caused by pywebview, feel free to submit a new issue. Please remember to specify under which operating system the bug occurs, as well as with other relevant information. In case of Linux, specify a distro you are using. ← [Development](https://pywebview.flowrl.com/3.7/contributing/development.html) [Donating](https://pywebview.flowrl.com/3.7/contributing/donating.html) → --- # Development | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/development.html#development) Development ============================================================================================ Before you get busy coding a new feature, create an issue and discuss the details in the issue tracker. [#](https://pywebview.flowrl.com/3.7/contributing/development.html#environment-set-up) Environment set-up ---------------------------------------------------------------------------------------------------------- This guide assumes you have a [GitHub (opens new window)](https://github.com/) account, as well as [Python 3 (opens new window)](https://python.org/) , [virtualenv (opens new window)](https://virtualenv.pypa.io/en/stable/) and [Git (opens new window)](https://git-scm.com/) installed. The guide is written for Bash, for Windows you can use for example Bash bundled with Git. * [Fork (opens new window)](https://github.com/r0x0r/pywebview/fork) _pywebview_ * Clone your forked repository git clone https://github.com//pywebview cd pywebview * Create a virtual environment virtualenv -p python3 venv source venv/bin/activate pip install -e . pip install pytest * Hello world python examples/simple_browser.py [#](https://pywebview.flowrl.com/3.7/contributing/development.html#development-work-flow) Development work-flow ---------------------------------------------------------------------------------------------------------------- * Create and checkout a new branch git checkout -b new-branch master * Make your changes * Run tests pytest tests * Commit and push your work git add . git commit -m "Your commit message goes here" git push -u origin new-branch * [Create a pull request (opens new window)](https://help.github.com/articles/creating-a-pull-request/) [#](https://pywebview.flowrl.com/3.7/contributing/development.html#testing) Testing ------------------------------------------------------------------------------------ pywebview uses [pytest (opens new window)](https://docs.pytest.org/en/latest/) for testing. To run all the tests in the project root directory pytest tests To run a specific test pytest tests/test_simple_browser.py Tests cover only trivial mistakes, syntax errors, exceptions and such. In other words there is no functional testing. Each test verifies that a pywebview window can be opened and exited without errors when run under different scenarios. Sometimes test fail / stuck randomly. The cause of the issue is not known, any help on resolving random fails is greatly appreciated. [#](https://pywebview.flowrl.com/3.7/contributing/development.html#learning) Learning -------------------------------------------------------------------------------------- ### [#](https://pywebview.flowrl.com/3.7/contributing/development.html#windows) Windows * [Windows Forms documentation (opens new window)](https://docs.microsoft.com/en-us/dotnet/framework/winforms/) * [Windows Forms API (opens new window)](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms) ### [#](https://pywebview.flowrl.com/3.7/contributing/development.html#macos) macOS * [pyobjc (opens new window)](https://pythonhosted.org/pyobjc/) . Converting Objective C syntax to Python can be tricky at first. Be sure to check out the [pyobjc intro (opens new window)](https://pythonhosted.org/pyobjc/core/intro.html) . * [AppKit (opens new window)](https://developer.apple.com/documentation/appkit) * [WebKit (opens new window)](https://developer.apple.com/documentation/webkit) ### [#](https://pywebview.flowrl.com/3.7/contributing/development.html#linux) Linux * [PyGObject API reference (opens new window)](https://lazka.github.io/pgi-docs/) ### [#](https://pywebview.flowrl.com/3.7/contributing/development.html#qt) Qt * [Qt for Python Documentation (opens new window)](https://doc.qt.io/qtforpython-5/contents.html) * [Qt5 documentation (opens new window)](https://doc.qt.io/qt-5/index.html) * [PySide2 QtWidgets (opens new window)](https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/index.html) [Bug reporting](https://pywebview.flowrl.com/3.7/contributing/bug_reporting.html) → --- # Usage | pywebview [#](https://pywebview.flowrl.com/3.7/guide/usage.html#usage) Usage =================================================================== [#](https://pywebview.flowrl.com/3.7/guide/usage.html#basics) Basics --------------------------------------------------------------------- The bare minimum to get _pywebview_ up and running is import webview window = webview.create_window('Woah dude!', 'https://pywebview.flowrl.com') webview.start() The `create_window` function returns a window instance that provides a number of both window manipulation and DOM related functions. You may create as many windows as you wish. Windows created after the GUI loop is started are shown immediately. All the opened windows are stored as a list in `webview.windows`. The windows are stored in a creation order. The `create_window` second argument `url` can point to a remote or a local path. Alternatively, you can load HTML by setting the `html` parameter. import webview webview.create_window('Woah dude!', html='

Woah dude!

') webview.start() Note that if both `url` and `html` are set, `html` takes precedence. _pywebview_ gives a choice of several web renderers. To change a web renderer, set the `gui` parameter of the `start` function to the desired value (e.g `cef` or `qt`). See [Renderer](https://pywebview.flowrl.com/3.7/guide/renderer.html) for details. [#](https://pywebview.flowrl.com/3.7/guide/usage.html#http-server) HTTP server ------------------------------------------------------------------------------- _pywebview_ provides a WSGI-compatible HTTP server. To start a HTTP server set the url to a local entry point (without a protocol schema) and set the `http_server` parameter of the `start` function to `True` import webview webview.create_window('Woah dude!', 'index.html') webview.start(http_server=True) If you wish to use an external WSGI compatible HTTP server with _pywebview_, you can pass a server object as an URL, ie. `http_server` parameter does not need to be set in this case. from flask import Flask import webview server = Flask(__name__, static_folder='./assets', template_folder='./templates') webview.create_window('Flask example', server) webview.start() [#](https://pywebview.flowrl.com/3.7/guide/usage.html#threading-model) Threading model --------------------------------------------------------------------------------------- `webview.start` starts a GUI loop and is a blocking function. With the GUI loop being blocking, you must execute your backend logic in a separate thread or a process. You may launch a thread or a process manually. Alternatively you can execute your code by passing your function as the first parameter `func` to `start`. The second parameter sets the function's arguments. This approach starts a thread behind the scenes and is identical to starting a thread manually. import webview def custom_logic(window): window.toggle_fullscreen() window.evaluate_js('alert("Nice one brother")') window = webview.create_window('Woah dude!', html='

Woah dude!

') webview.start(custom_logic, window) # anything below this line will be executed after program is finished executing pass [#](https://pywebview.flowrl.com/3.7/guide/usage.html#make-python-and-javascript-talk-with-each-other) Make Python and Javascript talk with each other ======================================================================================================================================================= You can think of custom logic as a backend that communicates with frontend code in the HTML/JS realm. Now how would you make two to communicate with each other? _pywebview_ offers a two way JS-Python bridge that lets you both execute Javascript from Python (via `evaluate_js`) and Python code from Javascript (via `js_api` and `expose`). See [interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) for details. Another way is to run a Python web server (like Flask or Bottle) in custom logic and make frontend code make API calls to it. That would be identical to a typical web application. This approach is suitable, for example, for porting an existing web application to a desktop application. See [Architecture](https://pywebview.flowrl.com/3.7/guide/architecture.html) for more information on both approaches. ← [Installation](https://pywebview.flowrl.com/3.7/guide/installation.html) [API](https://pywebview.flowrl.com/3.7/guide/api.html) → --- # Donating | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/donating.html#donating) Donating =================================================================================== [#](https://pywebview.flowrl.com/3.7/contributing/donating.html#recurrring-pledge) Recurrring pledge ----------------------------------------------------------------------------------------------------- Recurring pledges come perks, like getting email support or featuring your name or logo in the project repository [![Become a Patron!](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/bePatron?u=13226105) [![](https://opencollective.com/pywebview/donate/button@2x.png?color=blue)](https://opencollective.com/pywebview/donate) [#](https://pywebview.flowrl.com/3.7/contributing/donating.html#one-time-donations) One-time donations ------------------------------------------------------------------------------------------------------- We accept donations via Paypal [![](https://pywebview.flowrl.com/paypal.png)](http://bit.ly/2eg2Z5P) ← [Bug reporting](https://pywebview.flowrl.com/3.7/contributing/bug_reporting.html) [Documentation](https://pywebview.flowrl.com/3.7/contributing/documentation.html) → --- # Documentation | pywebview [#](https://pywebview.flowrl.com/3.7/contributing/documentation.html#documentation) Documentation ================================================================================================== One way to contribute is to improve documentation on this side. Each page has a 'Help us improve this page' link at the bottom of the page. By clicking the link you can create a pull request with your changes. You need a Github account to edit pages. ← [Donating](https://pywebview.flowrl.com/3.7/contributing/donating.html) --- # Application architecture | pywebview [#](https://pywebview.flowrl.com/3.7/guide/architecture.html#application-architecture) Application architecture ================================================================================================================ There are two ways to build your application using _pywebview_: 1. By running a local web server 2. Serverless with _pywebview_'s JS API or `window.expose` and serving local files. [#](https://pywebview.flowrl.com/3.7/guide/architecture.html#local-web-server) Local web server ------------------------------------------------------------------------------------------------ Running a local web server is a traditional way to build your local application. This way everything is served from a local web server and _pywebview_ points to the URL provided by the server. In this model the server is responsible for both serving static contents and handling API calls. When building an application using a web server, you should protect your API calls against CSRF attacks. See [security](https://pywebview.flowrl.com/3.7/guide/security.html) for more information. See an example [Flask-based application (opens new window)](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) **Pros**: * Ability to pack an existing web application as a local one. * Easier debugging with an external browser. **Cons** * Has to rely on a third party server software for client-server communication. * Security considerations must be taken into account [#](https://pywebview.flowrl.com/3.7/guide/architecture.html#serverless) Serverless ------------------------------------------------------------------------------------ Another way to build an application is to use _pywebview_'s provided JS API or `windows.expose` and serve static files locally. _pywebview_ offers a simple built-in web server that is good enough for serving local files. To use a local web server, set url to a local file and start the application with `webview.start(http_server=True)`. Note that the built-in HTTP server serves only local files and does not offer any API calls. Refer to [interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) for details on how to pass data between Python and Javascript. See an example [serverless application (opens new window)](https://github.com/r0x0r/pywebview/tree/master/examples/todos) **Pros**: * No external dependencies * More straightforward architecture * No risk of CSRF attacks **Cons** * Debugging has to be done inside the application using provided debugging tools * EdgeHTML cannot serve local files. ← [API](https://pywebview.flowrl.com/3.7/guide/api.html) [Debugging](https://pywebview.flowrl.com/3.7/guide/debugging.html) → --- # Debugging | pywebview [#](https://pywebview.flowrl.com/3.7/guide/debugging.html#debugging) Debugging =============================================================================== To debug Javascript, set the `debug` parameter of `start` to `True` import webview webview.create_window('https://pywebview.flowrl.com/hello') webview.start(debug=True) This will enable web inspector on macOS, GTK and QT (QTWebEngine only). To open the web inspector, right click on the page and select Inspect. To debug EdgeHTML, you need to install [Microsoft Edge DevTools Preview (opens new window)](https://www.microsoft.com/en-us/p/microsoft-edge-devtools-preview/9mzbfrmz0mnj) . Launch the application and select your application from the list of running WebViews. The `debug` flag also routes `console.logs` to the Python console. There is no way to attach an external debugger to MSHTML. The `debug` flag enables Javascript error reporting and right-click context menu on Windows. ← [Application architecture](https://pywebview.flowrl.com/3.7/guide/architecture.html) [Interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) → --- # Interdomain communication | pywebview [#](https://pywebview.flowrl.com/3.7/guide/interdomain.html#interdomain-communication) Interdomain communication ================================================================================================================= [#](https://pywebview.flowrl.com/3.7/guide/interdomain.html#invoke-javascript-from-python) Invoke Javascript from Python ------------------------------------------------------------------------------------------------------------------------- `window.evaluate_js(code, callback=None)` allows you to execute arbitrary Javascript code with a last value returned synchronously. If callback function is supplied, then promises are resolved and the callback function is called with the result as a parameter. Javascript types are converted to Python types, eg. JS objects to dicts, arrays to lists, undefined to None. Note that due implementation limitations the string 'null' will be evaluated to None. You must escape \\n and \\r among other escape sequences if they present in Javascript code. Otherwise they get parsed by Python. r'strings' is a recommended way to load Javascript. For GTK WebKit2 versions older than 2.22, there is a limit of about ~900 characters for a value returned by `evaluate_js`. [#](https://pywebview.flowrl.com/3.7/guide/interdomain.html#invoke-python-from-javascript) Invoke Python from Javascript ------------------------------------------------------------------------------------------------------------------------- Invoking Python functions from Javascript can be done with two different approaches. * by exposing an instance of a Python class to the `js_api` of `create_window`. All the callable methods of the class will be exposed to the JS domain as `pywebview.api.method_name` with correct parameter signatures. Method name must not start with an underscore. See an [example](https://pywebview.flowrl.com/3.7/examples/js_api.html) . * by passing your function(s) to window object's `expose(func)`. This will expose a function or functions to the JS domain as `pywebview.api.func_name`. Unlike JS API, `expose` allows to expose functions also at the runtime. If there is a name clash between JS API and functions exposed this way, the latter takes precedence. See an [example](https://pywebview.flowrl.com/3.7/examples/expose.html) . Exposed function returns a promise that is resolved to its result value. Exceptions are rejected and encapsulated inside a Javascript `Error` object. Stacktrace is available via `error.stack`. Functions are executed in separate threads and are not thread-safe. `window.pywebview.api` is not guaranteed to be available on `window.onload`. Subscribe to `window.pywebviewready` instead to make sure that `window.pywebview.api` is ready. [Example](https://pywebview.flowrl.com/3.7/examples/js_api.html) . ← [Debugging](https://pywebview.flowrl.com/3.7/guide/debugging.html) [Freezing](https://pywebview.flowrl.com/3.7/guide/freezing.html) → --- # Freezing | pywebview [#](https://pywebview.flowrl.com/3.7/guide/freezing.html#freezing) Freezing ============================================================================ [#](https://pywebview.flowrl.com/3.7/guide/freezing.html#macos) macOS ---------------------------------------------------------------------- Use [py2app (opens new window)](https://py2app.readthedocs.io/en/latest/) . For a reference setup.py for py2app, look [here (opens new window)](https://github.com/r0x0r/pywebview/blob/master/examples/py2app_setup.py) . [#](https://pywebview.flowrl.com/3.7/guide/freezing.html#windows) Windows -------------------------------------------------------------------------- Use [pyinstaller (opens new window)](https://www.pyinstaller.org/) . If you are using _PyInstaller>=3.6_, it should work out of the box as there is hook that takes care of the bundling of necessary dlls. Therefore, this version of PyInstaller is the recommended one. Should you need to use prior versions of PyInstaller (<=3.5), you will need to bundle the dlls yourself. Either [WebBrowserInterop.x86.dll (opens new window)](https://github.com/r0x0r/pywebview/blob/master/webview/lib/WebBrowserInterop.x86.dll) or [WebBrowserInterop.x64.dll (opens new window)](https://github.com/r0x0r/pywebview/blob/master/webview/lib/WebBrowserInterop.x64.dll) depending on whether you build against 32-bit or 64-bit Python. The DLLs bundled with _pywebview_ and are located in the `site-packages/webview/lib` directory. [#](https://pywebview.flowrl.com/3.7/guide/freezing.html#linux) Linux ---------------------------------------------------------------------- Use [pyinstaller (opens new window)](https://www.pyinstaller.org/) . ← [Interdomain communication](https://pywebview.flowrl.com/3.7/guide/interdomain.html) [Security](https://pywebview.flowrl.com/3.7/guide/security.html) → --- # Security | pywebview [#](https://pywebview.flowrl.com/3.7/guide/security.html#security) Security ============================================================================ When using a local web server, you must protect your API from unauthorized access. [CSRF attacks (opens new window)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) can be a major problem if API is not protected in an adequate matter. _pywebview_ generates a session-unique token that is exposed both to Python `webview.token` and DOM `window.pywebview.token`. See [Flask app (opens new window)](https://github.com/r0x0r/pywebview/tree/master/examples/flask_app) for an example. For building a custom solution refer to [this document (opens new window)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet) for API securing approaches. A library like [flask-seasurf (opens new window)](https://flask-seasurf.readthedocs.io/en/latest/) alongside Flask can be used too. ← [Freezing](https://pywebview.flowrl.com/3.7/guide/freezing.html) [Virtual environment](https://pywebview.flowrl.com/3.7/guide/virtualenv.html) → --- # Virtual environment | pywebview [#](https://pywebview.flowrl.com/3.7/guide/virtualenv.html#virtual-environment) Virtual environment ==================================================================================================== If you create a virtual environment using the built-in Python on macOS, a pywebview window will have issues with keyboard focus and Cmd+Tab. The issue can be avoided by using other Python installation as described [here (opens new window)](https://virtualenv.pypa.io/en/stable/userguide/#using-virtualenv-without-bin-python) . For example to use Python 3 via [Homebrew (opens new window)](https://brew.sh/) . brew install python3 virtualenv pywebview_env -p python3 ← [Security](https://pywebview.flowrl.com/3.7/guide/security.html) [Web engine](https://pywebview.flowrl.com/3.7/guide/renderer.html) → --- # Web engine | pywebview [#](https://pywebview.flowrl.com/3.7/guide/renderer.html#web-engine) Web engine ================================================================================ The following renderers are used on each platform | Platform | Code | Renderer | Provider | Browser compatibility | | --- | --- | --- | --- | --- | | GTK | gtk | WebKit | WebKit2 | | | macOS | | WebKit | WebKit.WKWebView (bundled with OS) | | | QT | qt | WebKit | QtWebEngine / QtWebKit | | | Windows | edgechromium | Chromium | \> .NET Framework 4.6.2 and Edge Runtime installed | Ever-green Chromium | | Windows | edgehtml | EdgeHTML | \> .NET Framework 4.6.2 and Windows 10 build 17110 | | | Windows | mshtml | MSHTML | MSHTML via .NET / System.Windows.Forms.WebBrowser | IE11 (Windows 10/8/7) | | Windows | cef | CEF | CEF Python | Chrome 66 | On Windows renderer is chosen in the following order: `edgechromium`, `edgehtml`, `mshtml`. `mshtml` is the only renderer that is guaranteed to be available on any system. Note that Edge Runtime must be installed in order to use Edge Chromium on Windows. You can download it from [here (opens new window)](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) . Distribution guidelines are found [here (opens new window)](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) . To change a default renderer set either `PYWEBVIEW_GUI` environment variable or pass the rendered value to `webview.start(gui=code)` function parameter. Check for available values in the Code column from the table above. For example to use CEF on Windows PYWEBVIEW_GUI=cef or import webview webview.start(gui='cef') If you wish to pass custom settings to CEF, refer to [this example](https://pywebview.flowrl.com/3.7/examples/cef.html) To force QT on Linux systems PYWEBVIEW_GUI=qt or import webview webview.start(gui='qt') [#](https://pywebview.flowrl.com/3.7/guide/renderer.html#known-issues-and-limitations) Known issues and limitations ==================================================================================================================== [#](https://pywebview.flowrl.com/3.7/guide/renderer.html#gtk-webkit2) GTK WebKit2 ---------------------------------------------------------------------------------- * Versions of WebKit2 older than 2.2 has a limitation of 1000 characters of the Javascript result returned by `evaluate_js`. `get_elements` is not supported for this reason. [#](https://pywebview.flowrl.com/3.7/guide/renderer.html#qtwebkit) QtWebKit ---------------------------------------------------------------------------- * Debugging is not supported [#](https://pywebview.flowrl.com/3.7/guide/renderer.html#edgehtml) EdgeHTML ---------------------------------------------------------------------------- * `file://` URLs are not fully supported. While such URLs can be loaded, associated resources such as images or stylesheets cannot. * Destroying a window via `window.destroy()` and starting a new instance will crash the program. * Running the program under elevated privileges will throw an exception. * Access to localhost URLs is restricted by default. To overcome this the LoopbackExempt settings are modified on _pywebview_ launch, which triggers a UAC prompt. This only happens once and only if LoopbackExempt setting is not set. You can manually set this setting beforehand to avoid UAC: `checknetisolation LoopbackExempt -a -n="Microsoft.Win32WebViewHost_cw5n1h2txyewy"` (must be run as an admin). ← [Virtual environment](https://pywebview.flowrl.com/3.7/guide/virtualenv.html) --- # API | pywebview [#](https://pywebview.flowrl.com/3.7/guide/api.html#api) API ============================================================= [#](https://pywebview.flowrl.com/3.7/guide/api.html#webview-create-window) webview.create\_window -------------------------------------------------------------------------------------------------- webview.create_window(title, url='', html='', js_api=None, width=800, height=600, \ x=None, y=None, resizable=True, fullscreen=False, \ min_size=(200, 100), hidden=False, frameless=False, \ minimized=False, on_top=False, confirm_close=False, \ background_color='#FFF', text_select=False) Create a new _pywebview_ window and returns its instance. Window is not shown until the GUI loop is started. If the function is invoked during the GUI loop, the window is displayed immediately. * `title` - Window title * `url` - URL to load. If the URL does not have a protocol prefix, it is resolved as a path relative to the application entry point. Alternatively a WSGI server object can be passed to start a local web server. * `html` - HTML code to load. If both URL and HTML are specified, HTML takes precedence. * `js_api` - Expose a python object to the DOM of the current `pywebview` window. Methods of the `js_api` object can be executed from Javascript by calling `window.pywebview.api.()`. Please note that the calling Javascript function receives a promise that will contain the return value of the python function. Only basic Python objects (like int, str, dict, ...) can be returned to Javascript. * `width` - Window width. Default is 800px. * `height` - Window height. Default is 600px. * `x` - Window x coordinate. Default is centered. * `y` - Window y coordinate. Default is centered. * `resizable` - Whether window can be resized. Default is True * `fullscreen` - Start in fullscreen mode. Default is False * `min_size` - a (width, height) tuple that specifies a minimum window size. Default is 200x100 * `hidden` - Create a window hidden by default. Default is False * `frameless` - Create a frameless window. Default is False. * `easy_drag` - Easy drag mode for frameless windows. Window can be moved by dragging any point. Default is True. Note that easy\_drag has no effect with normal windows. To control dragging on an element basis, see [drag area](https://pywebview.flowrl.com/3.7/guide/api.html#drag-area) for details. * `minimized` - Start in minimized mode * `on_top` - Set window to be always on top of other windows. Default is False. * `confirm_close` - Whether to display a window close confirmation dialog. Default is False * `background_color` - Background color of the window displayed before WebView is loaded. Specified as a hex color. Default is white. * `transparent` - Create a transparent window. Not supported on Windows. Default is False. Note that this setting does not hide or make window chrome transparent. To hide window chrome set `frameless` to True. * `text_select` - Enables document text selection. Default is False. To control text selection on per element basis, use [user-select (opens new window)](https://developer.mozilla.org/en-US/docs/Web/CSS/user-select) CSS property. [#](https://pywebview.flowrl.com/3.7/guide/api.html#webview-start) webview.start --------------------------------------------------------------------------------- webview.start(func=None, args=None, localization={}, gui=None, debug=False, \ http_server=False, user_agent=None) Start a GUI loop and display previously created windows. This function must be called from a main thread. * `func` - function to invoke upon starting the GUI loop. * `args` - function arguments. Can be either a single value or a tuple of values. * `localization` - a dictionary with localized strings. Default strings and their keys are defined in localization.py * `gui` - force a specific GUI. Allowed values are `cef`, `qt` or `gtk` depending on a platform. See [Renderer](https://pywebview.flowrl.com/3.7/guide/renderer.html) for details. * `debug` - enable debug mode. See [Debugging](https://pywebview.flowrl.com/3.7/guide/debugging.html) for details. * `http_server` - enable built-in HTTP server. If enabled, local files will be served using a local HTTP server on a random port. For each window, a separate HTTP server is spawned. This option is ignored for non-local URLs. * `user_agent` - change user agent string. Not supported in EdgeHTML. ### [#](https://pywebview.flowrl.com/3.7/guide/api.html#examples) Examples * [Simple window](https://pywebview.flowrl.com/3.7/examples/open_url.html) * [Multi-window](https://pywebview.flowrl.com/3.7/examples/multiple_windows.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#webview-screens) webview.screens ------------------------------------------------------------------------------------- webview.screens Return a list of available displays (as `Screen` objects) with the primary display as the first element of the list. ### [#](https://pywebview.flowrl.com/3.7/guide/api.html#examples-2) Examples * [Simple window](https://pywebview.flowrl.com/3.7/examples/screens.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#webview-token) webview.token --------------------------------------------------------------------------------- webview.token A CSRF token property unique to the session. The same token is exposed as `window.pywebview.token`. See [Security](https://pywebview.flowrl.com/3.7/guide/security.html) for usage details. [#](https://pywebview.flowrl.com/3.7/guide/api.html#screen-object) Screen object ================================================================================= Represents a display found on the system. [#](https://pywebview.flowrl.com/3.7/guide/api.html#height) height ------------------------------------------------------------------- screen.height Get display height. [#](https://pywebview.flowrl.com/3.7/guide/api.html#width) width ----------------------------------------------------------------- screen.width Get display width. [#](https://pywebview.flowrl.com/3.7/guide/api.html#window-object) Window object ================================================================================= Represents a window that hosts webview. `window` object is returned by `create_window` function. [#](https://pywebview.flowrl.com/3.7/guide/api.html#on-top) on\_top -------------------------------------------------------------------- window.on_top Get or set whether the window is always on top [#](https://pywebview.flowrl.com/3.7/guide/api.html#x) x --------------------------------------------------------- window.x Get X coordinate of the top-left corrner of the window [#](https://pywebview.flowrl.com/3.7/guide/api.html#y) y --------------------------------------------------------- window.y Get Y coordinate of the top-left corrner of the window [#](https://pywebview.flowrl.com/3.7/guide/api.html#width-2) width ------------------------------------------------------------------- window.width Get width of the window [#](https://pywebview.flowrl.com/3.7/guide/api.html#height-2) height --------------------------------------------------------------------- window.height Get height of the window [#](https://pywebview.flowrl.com/3.7/guide/api.html#create-file-dialog) create\_file\_dialog --------------------------------------------------------------------------------------------- window.create_file_dialog(dialog_type=OPEN_DIALOG, directory='', allow_multiple=False, save_filename='', file_types=())` Create an open file (`webview.OPEN_DIALOG`), open folder (`webview.FOLDER_DIALOG`) or save file (`webview.SAVE_DIALOG`) dialog. Return a tuple of selected files, None if cancelled. * `allow_multiple=True` enables multiple selection. * `directory` Initial directory. * `save_filename` Default filename for save file dialog. * `file_types` A tuple of supported file type strings in the open file dialog. A file type string must follow this format `"Description (*.ext1;*.ext2...)"`. If the argument is not specified, then the `"All files (*.*)"` mask is used by default. The 'All files' string can be changed in the localization dictionary. ### [#](https://pywebview.flowrl.com/3.7/guide/api.html#examples-3) Examples * [Open-file dialog](https://pywebview.flowrl.com/3.7/examples/open_file_dialog.html) * [Save-file dialog](https://pywebview.flowrl.com/3.7/examples/save_file_dialog.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#destroy) destroy --------------------------------------------------------------------- window.destroy() Destroy the window. [Example](https://pywebview.flowrl.com/3.7/examples/destroy_window.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#evaluate-js) evaluate\_js ------------------------------------------------------------------------------ window.evaluate_js(script, callback=None) Execute Javascript code. The last evaluated expression is returned. If callback function is supplied, then promises are resolved and the callback function is called with the result as a parameter. Javascript types are converted to Python types, eg. JS objects to dicts, arrays to lists, undefined to None. Note that due implementation limitations the string 'null' will be evaluated to None. You must escape \\n and \\r among other escape sequences if they present in Javascript code. Otherwise they get parsed by Python. r'strings' is a recommended way to load Javascript. For GTK WebKit2 versions older than 2.22, there is a limit of about ~900 characters for a value returned by `evaluate_js`. [#](https://pywebview.flowrl.com/3.7/guide/api.html#get-current-url) get\_current\_url --------------------------------------------------------------------------------------- window.get_current_url() Return the current URL. None if no url is loaded. [Example](https://pywebview.flowrl.com/3.7/examples/get_current_url.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#get-elements) get\_elements -------------------------------------------------------------------------------- window.get_elements(selector) Return the serialized DOM element by its selector. None if no element matches. For GTK you must have WebKit2 2.22 or greater to use this function. [Example](https://pywebview.flowrl.com/3.7/examples/get_elements.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#hide) hide --------------------------------------------------------------- window.hide() Hide the window. [Example](https://pywebview.flowrl.com/3.7/examples/show_hide.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#load-css) load\_css ------------------------------------------------------------------------ window.load_css(css) Load CSS as a string. [Example](https://pywebview.flowrl.com/3.7/examples/css_load.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#load-html) load\_html -------------------------------------------------------------------------- window.load_html(content, base_uri=base_uri()) Load HTML code. Base URL for resolving relative URLs is set to the directory the program is launched from. Note that you cannot use hashbang anchors when HTML is loaded this way. [Example](https://pywebview.flowrl.com/3.7/examples/html_load.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#load-url) load\_url ------------------------------------------------------------------------ window.load_url(url) Load a new URL. [Example](https://pywebview.flowrl.com/3.7/examples/change_url.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#minimize) minimize ----------------------------------------------------------------------- window.minimize() Minimize window. [Example](https://pywebview.flowrl.com/3.7/examples/minimize.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#move) move --------------------------------------------------------------- window.move(x, y) Move window to a new position. [Example](https://pywebview.flowrl.com/3.7/examples/move_window.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#resize) resize ------------------------------------------------------------------- window.resize(width, height, fix_point=FixPoint.NORTH | FixPoint.WEST) Resize window. Optional parameter fix\_point specifies in respect to which point the window is resized. The parameter accepts values of the `webview.window.FixPoint` enum (`NORTH`, `SOUTH`, `EAST`, `WEST`) [Example](https://pywebview.flowrl.com/3.7/examples/minimize.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#restore) restore --------------------------------------------------------------------- window.restore() Restore minimized window. [Example](https://pywebview.flowrl.com/3.7/examples/minimize.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#set-title) set\_title -------------------------------------------------------------------------- window.set_title(title) Change the title of the window. [Example](https://pywebview.flowrl.com/3.7/examples/window_title_change.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#show) show --------------------------------------------------------------- window.show() Show the window if it is hidden. Has no effect otherwise [Example](https://pywebview.flowrl.com/3.7/examples/show_hide.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#toggle-fullscreen) toggle\_fullscreen ------------------------------------------------------------------------------------------ window.toggle_fullscreen() Toggle fullscreen mode on the active monitor. [Example](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events) Events =================================================================== Window object has a number of lifecycle events. To subscribe to an event, use the `+=` syntax, e.g. `window.events.loaded += func`. The func will be invoked, when event is fired. Duplicate subscriptions are ignored and function is invoked only once for duplicate subscribers. To unsubscribe `window.events.loaded -= func`. [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-closed) events.closed --------------------------------------------------------------------------------- Event fired just before pywebview window is closed. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-closing) events.closing ----------------------------------------------------------------------------------- Event fired when pywebview window is about to be closed. If confirm\_quit is set, then this event is fired before the close confirmation is displayed. If event handler returns False, the close operation will be cancelled. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-loaded) events.loaded --------------------------------------------------------------------------------- Event fired when DOM is ready. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-minimized) events.minimized --------------------------------------------------------------------------------------- Event fired when window is minimized. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-restore) events.restore ----------------------------------------------------------------------------------- Event fired when window is restored. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-maximized) events.maximized --------------------------------------------------------------------------------------- Event fired when window is maximized (fullscreen on macOS) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-resized) events.resized ----------------------------------------------------------------------------------- Event fired when pywebview window is resized. Event handler can either have no or accept (width, height) arguments. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#events-shown) events.shown ------------------------------------------------------------------------------- Event fired when pywebview window is shown. [Example](https://pywebview.flowrl.com/3.7/examples/events.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#dom-events) DOM events =========================================================================== _pywebview_ exposes a `window.pywebviewready` DOM event that is fired when `window.pywebview` is created. [Example](https://pywebview.flowrl.com/3.7/examples/js_api.html) [#](https://pywebview.flowrl.com/3.7/guide/api.html#drag-area) Drag area ========================================================================= With a frameless _pywebview_ window, A window can be moved or dragged by adding a special class called `pywebview-drag-region` in your html
This div element can be used to moved or drag your window like a native OS window
The magic class name can be overriden by re-assigning the `webview.DRAG_REGION_SELECTOR` constant. [Example](https://pywebview.flowrl.com/3.7/examples/js_api.html) ← [Usage](https://pywebview.flowrl.com/3.7/guide/usage.html) [Application architecture](https://pywebview.flowrl.com/3.7/guide/architecture.html) → --- # Change URL | pywebview [#](https://pywebview.flowrl.com/3.7/examples/change_url.html#change-url) Change URL ===================================================================================== Change URL ten seconds after the first URL is loaded. import webview import time def change_url(window): # wait a few seconds before changing url: time.sleep(10) # change url: window.load_url('https://woot.fi') if __name__ == '__main__': window = webview.create_window('URL Change Example', 'https://pywebview.flowrl.com/hello') webview.start(change_url, window) ← [CEF support](https://pywebview.flowrl.com/3.7/examples/cef.html) [CSS load](https://pywebview.flowrl.com/3.7/examples/css_load.html) → --- # CSS load | pywebview [#](https://pywebview.flowrl.com/3.7/examples/css_load.html#css-load) CSS load =============================================================================== Change window background color by loading CSS import webview def load_css(window): window.load_css('body { background: red !important; }') if __name__ == '__main__': window = webview.create_window('Load CSS Example', 'https://pywebview.flowrl.com/hello') webview.start(load_css, window) ← [Change URL](https://pywebview.flowrl.com/3.7/examples/change_url.html) [Quit confirmation dialog](https://pywebview.flowrl.com/3.7/examples/close_confirm.html) → --- # Quit confirmation dialog | pywebview [#](https://pywebview.flowrl.com/3.7/examples/close_confirm.html#quit-confirmation-dialog) Quit confirmation dialog ==================================================================================================================== import webview """ This example demonstrates a webview window with a quit confirmation dialog. """ if __name__ == '__main__': # Create a standard webview window webview.create_window('Confirm Close Example', 'https://pywebview.flowrl.com/hello', confirm_close=True) webview.start() ← [CSS load](https://pywebview.flowrl.com/3.7/examples/css_load.html) [Debugging](https://pywebview.flowrl.com/3.7/examples/debug.html) → --- # Debugging | pywebview [#](https://pywebview.flowrl.com/3.7/examples/debug.html#debugging) Debugging ============================================================================== To open up debugging console, right click on an element and select Inspect. import webview if __name__ == '__main__': webview.create_window('Debug window', 'https://pywebview.flowrl.com/hello') webview.start(debug=True) ← [Quit confirmation dialog](https://pywebview.flowrl.com/3.7/examples/close_confirm.html) [Destroy window](https://pywebview.flowrl.com/3.7/examples/destroy_window.html) → --- # Events | pywebview [#](https://pywebview.flowrl.com/3.7/examples/events.html#events) Events ------------------------------------------------------------------------- Subscribe and unsubscribe to pywebview events. import webview import time """ This example demonstrates how to handle pywebview events. """ def on_closed(): print('pywebview window is closed') def on_closing(): print('pywebview window is closing') def on_shown(): print('pywebview window shown') def on_minimized(): print('pywebview window minimized') def on_restored(): print('pywebview window restored') def on_maximized(): print('pywebview window maximized') def on_loaded(): print('DOM is ready') # unsubscribe event listener webview.windows[0].loaded -= on_loaded webview.windows[0].load_url('https://pywebview.flowrl.com/hello') def on_resized(width, height): print('pywebview window is resized. new dimensions are {width} x {height}'.format(width=width, height=height)) def on_moved(x, y): print('pywebview window is moved. new coordinates are x: {x}, y: {y}'.format(x=x, y=y)) if __name__ == '__main__': window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/', confirm_close=True) window.events.closed += on_closed window.events.closing += on_closing window.events.shown += on_shown window.events.loaded += on_loaded window.events.minimized += on_minimized window.events.maximized += on_maximized window.events.restored += on_restored window.events.resized += on_resized window.events.moved += on_moved webview.start() ← [Destroy window](https://pywebview.flowrl.com/3.7/examples/destroy_window.html) [Frameless window](https://pywebview.flowrl.com/3.7/examples/frameless.html) → --- # Destroy window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/destroy_window.html#destroy-window) Destroy window ------------------------------------------------------------------------------------------------- Programmatically destroy created window after five seconds. import webview import time def destroy(window): # show the window for a few seconds before destroying it: time.sleep(5) print('Destroying window..') window.destroy() print('Destroyed!') if __name__ == '__main__': window = webview.create_window('Destroy Window Example', 'https://pywebview.flowrl.com/hello') webview.start(destroy, window) print('Window is destroyed') ← [Debugging](https://pywebview.flowrl.com/3.7/examples/debug.html) [Events](https://pywebview.flowrl.com/3.7/examples/events.html) → --- # Frameless window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/frameless.html#frameless-window) Frameless window ================================================================================================ Create a frameless window. The window can be moved around by dragging any point. import webview if __name__ == '__main__': webview.create_window('Frameless window', 'http://pywebview.flowrl.com/hello', frameless=True) webview.start() ← [Events](https://pywebview.flowrl.com/3.7/examples/events.html) [Fullscreen window](https://pywebview.flowrl.com/3.7/examples/fullscreen.html) → --- # Fullscreen window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/fullscreen.html#fullscreen-window) Fullscreen window =================================================================================================== Create a fullscreen window. import webview if __name__ == '__main__': webview.create_window('Full-screen window', 'https://pywebview.flowrl.com/hello', fullscreen=True) webview.start() ← [Frameless window](https://pywebview.flowrl.com/3.7/examples/frameless.html) [Get DOM elements](https://pywebview.flowrl.com/3.7/examples/get_elements.html) → --- # Get DOM elements | pywebview [#](https://pywebview.flowrl.com/3.7/examples/get_elements.html#get-dom-elements) Get DOM elements =================================================================================================== Get DOM elements using a selector. import webview """ This example demonstrates how to retrieve a DOM element """ def get_elements(window): heading = window.get_elements('#heading') content = window.get_elements('.content') print('Heading:\n %s ' % heading[0]['outerHTML']) print('Content 1:\n %s ' % content[0]['outerHTML']) print('Content 2:\n %s ' % content[1]['outerHTML']) if __name__ == '__main__': html = """

Heading

Content 1
Content 2
""" window = webview.create_window('Get elements example', html=html) webview.start(get_elements, window) ← [Fullscreen window](https://pywebview.flowrl.com/3.7/examples/fullscreen.html) [Get current URL](https://pywebview.flowrl.com/3.7/examples/get_current_url.html) → --- # Get current URL | pywebview [#](https://pywebview.flowrl.com/3.7/examples/get_current_url.html#get-current-url) Get current URL ==================================================================================================== Print current URL after page is loaded. import webview def get_current_url(window): print(window.get_current_url()) if __name__ == '__main__': window = webview.create_window('Get current URL', 'https://pywebview.flowrl.com/hello') webview.start(get_current_url, window) ← [Get DOM elements](https://pywebview.flowrl.com/3.7/examples/get_elements.html) [Hide / show window](https://pywebview.flowrl.com/3.7/examples/hide_window.html) → --- # Hide / show window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/hide_window.html#hide-show-window) Hide / show window ==================================================================================================== Programmatically hide and show window import webview import time def hide_show(window): time.sleep(5) window.hide() time.sleep(5) window.show() if __name__ == '__main__': window = webview.create_window('Hide / show window', 'https://pywebview.flowrl.com/hello') webview.start(hide_show, window) ← [Get current URL](https://pywebview.flowrl.com/3.7/examples/get_current_url.html) [HTML load](https://pywebview.flowrl.com/3.7/examples/html_load.html) → --- # Javascript evaluation | pywebview [#](https://pywebview.flowrl.com/3.7/examples/js_evaluate.html#javascript-evaluation) Javascript evaluation ============================================================================================================ Evaluate Javascript from Python code. import webview def evaluate_js(window): result = window.evaluate_js( r""" var h1 = document.createElement('h1') var text = document.createTextNode('Hello pywebview') h1.appendChild(text) document.body.appendChild(h1) document.body.style.backgroundColor = '#212121' document.body.style.color = '#f2f2f2' // Return user agent 'User agent:\n' + navigator.userAgent; """ ) print(result) if __name__ == '__main__': window = webview.create_window('Run custom JavaScript') webview.start(evaluate_js, window) ← [HTML load](https://pywebview.flowrl.com/3.7/examples/html_load.html) [Javascript API](https://pywebview.flowrl.com/3.7/examples/js_api.html) → --- # HTML load | pywebview [#](https://pywebview.flowrl.com/3.7/examples/html_load.html#html-load) HTML load ================================================================================== Display content by loading HTML on the fly. import webview import time def load_html(window): time.sleep(5) window.load_html('

This is dynamically loaded HTML

') if __name__ == '__main__': window = webview.create_window('Load HTML Example', html='

This is initial HTML

') webview.start(load_html, window) ← [Hide / show window](https://pywebview.flowrl.com/3.7/examples/hide_window.html) [Javascript evaluation](https://pywebview.flowrl.com/3.7/examples/js_evaluate.html) → --- # Javascript API | pywebview [#](https://pywebview.flowrl.com/3.7/examples/js_api.html#javascript-api) Javascript API ========================================================================================= Create an application without a HTTP server. The application uses Javascript API object to communicate between Python and Javascript. import threading import time import sys import random import webview html = """

JS API Example

pywebview is not ready






""" class Api: def __init__(self): self.cancel_heavy_stuff_flag = False def init(self): response = { 'message': 'Hello from Python {0}'.format(sys.version) } return response def getRandomNumber(self): response = { 'message': 'Here is a random number courtesy of randint: {0}'.format(random.randint(0, 100000000)) } return response def doHeavyStuff(self): time.sleep(0.1) # sleep to prevent from the ui thread from freezing for a moment now = time.time() self.cancel_heavy_stuff_flag = False for i in range(0, 1000000): _ = i * random.randint(0, 1000) if self.cancel_heavy_stuff_flag: response = {'message': 'Operation cancelled'} break else: then = time.time() response = { 'message': 'Operation took {0:.1f} seconds on the thread {1}'.format((then - now), threading.current_thread()) } return response def cancelHeavyStuff(self): time.sleep(0.1) self.cancel_heavy_stuff_flag = True def sayHelloTo(self, name): response = { 'message': 'Hello {0}!'.format(name) } return response def error(self): raise Exception('This is a Python exception') if __name__ == '__main__': api = Api() window = webview.create_window('API example', html=html, js_api=api) webview.start() ← [Javascript evaluation](https://pywebview.flowrl.com/3.7/examples/js_evaluate.html) [Loading animation](https://pywebview.flowrl.com/3.7/examples/loading_animation.html) → --- # Loading animation | pywebview [#](https://pywebview.flowrl.com/3.7/examples/loading_animation.html#loading-animation) Loading animation ========================================================================================================== Create a loading animation that is displayed before application is loaded. import webview html = """
Loading...

Content is loaded!

""" if __name__ == '__main__': window = webview.create_window('Loading Animation', html=html, background_color='#333333') webview.start() ← [Javascript API](https://pywebview.flowrl.com/3.7/examples/js_api.html) [Link types](https://pywebview.flowrl.com/3.7/examples/links.html) → --- # Localization | pywebview [#](https://pywebview.flowrl.com/3.7/examples/localization.html#localization) Localization =========================================================================================== Localize system text string used by pywebview. For a full list of used string, refer to the `webview/localization.py` file. # -*- coding: utf-8 -*- import webview if __name__ == '__main__': localization = { 'global.saveFile': u'Сохранить файл', 'cocoa.menu.about': u'О программе', 'cocoa.menu.services': u'Cлужбы', 'cocoa.menu.view': u'Вид', 'cocoa.menu.hide': u'Скрыть', 'cocoa.menu.hideOthers': u'Скрыть остальные', 'cocoa.menu.showAll': u'Показать все', 'cocoa.menu.quit': u'Завершить', 'cocoa.menu.fullscreen': u'Перейти ', 'windows.fileFilter.allFiles': u'Все файлы', 'windows.fileFilter.otherFiles': u'Остальлные файльы', 'linux.openFile': u'Открыть файл', 'linux.openFiles': u'Открыть файлы', 'linux.openFolder': u'Открыть папку', } webview.create_window('Localization Example', 'https://pywebview.flowrl.com/hello') webview.start(localization=localization) ← [Link types](https://pywebview.flowrl.com/3.7/examples/links.html) [Minimum window size](https://pywebview.flowrl.com/3.7/examples/min_size.html) → --- # Link types | pywebview [#](https://pywebview.flowrl.com/3.7/examples/links.html#link-types) Link types ================================================================================ Demonstrate a difference between different link types import webview html = """

Links

Regular links are opened in the application window.

target='_blank' links are opened in an external browser.

""" if __name__ == '__main__': window = webview.create_window('Link types', html=html) webview.start() ← [Loading animation](https://pywebview.flowrl.com/3.7/examples/loading_animation.html) [Localization](https://pywebview.flowrl.com/3.7/examples/localization.html) → --- # Minimize / restore window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/minimize_window.html#minimize-restore-window) Minimize / restore window ====================================================================================================================== Minimize and restore window programmatically import webview from time import sleep def minimize(window): print('Window is started minimized') sleep(5) print('Restoring window') window.restore() sleep(5) print('Minimizing window') window.minimize() if __name__ == '__main__': window = webview.create_window('Minimize window example', html='

Minimize window

', minimized=True) webview.start(minimize, window) ← [Minimum window size](https://pywebview.flowrl.com/3.7/examples/min_size.html) [Move window](https://pywebview.flowrl.com/3.7/examples/move_window.html) → --- # Multi-window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/multiple_windows.html#multi-window) Multi-window =============================================================================================== Create multiple windows. import webview def third_window(): # Create a new window after the loop started third_window = webview.create_window('Window #3', html='

Third Window

') if __name__ == '__main__': # Master window master_window = webview.create_window('Window #1', html='

First window

') child_window = webview.create_window('Window #2', html='

Second window

') webview.start(third_window) ← [Move window](https://pywebview.flowrl.com/3.7/examples/move_window.html) [Open file dialog](https://pywebview.flowrl.com/3.7/examples/open_file_dialog.html) → --- # Minimum window size | pywebview [#](https://pywebview.flowrl.com/3.7/examples/min_size.html#minimum-window-size) Minimum window size ===================================================================================================== Set minimum window dimensions. import webview if __name__ == '__main__': # Create a resizable webview window with minimum size constraints webview.create_window('Minimum window size', 'https://pywebview.flowrl.com/hello', min_size=(400, 200)) webview.start() ← [Localization](https://pywebview.flowrl.com/3.7/examples/localization.html) [Minimize / restore window](https://pywebview.flowrl.com/3.7/examples/minimize_window.html) → --- # Open file dialog | pywebview [#](https://pywebview.flowrl.com/3.7/examples/open_file_dialog.html#open-file-dialog) Open file dialog ======================================================================================================= Create an open file dialog after page content is loaded. import webview def open_file_dialog(window): file_types = ('Image Files (*.bmp;*.jpg;*.gif)', 'All files (*.*)') result = window.create_file_dialog(webview.OPEN_DIALOG, allow_multiple=True, file_types=file_types) print(result) if __name__ == '__main__': window = webview.create_window('Open file dialog example', 'https://pywebview.flowrl.com/hello') webview.start(open_file_dialog, window) ← [Multi-window](https://pywebview.flowrl.com/3.7/examples/multiple_windows.html) [Open URL](https://pywebview.flowrl.com/3.7/examples/open_url.html) → --- # Open URL | pywebview [#](https://pywebview.flowrl.com/3.7/examples/open_url.html#open-url) Open URL =============================================================================== import webview if __name__ == '__main__': # Create a standard webview window window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/hello') webview.start() ← [Open file dialog](https://pywebview.flowrl.com/3.7/examples/open_file_dialog.html) [Resize window](https://pywebview.flowrl.com/3.7/examples/resize_window.html) → --- # Move window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/move_window.html#move-window) Move window ======================================================================================== Set window coordinates and move window after its creation. import webview from time import sleep def move(window): print('Window coordinates are ({0}, {1})'.format(window.x, window.y)) sleep(2) window.move(200, 200) print('Window coordinates are ({0}, {1})'.format(window.x, window.y)) if __name__ == '__main__': window = webview.create_window('Move window example', html='

Move window

', x=100, y=100) webview.start(move, window) ← [Minimize / restore window](https://pywebview.flowrl.com/3.7/examples/minimize_window.html) [Multi-window](https://pywebview.flowrl.com/3.7/examples/multiple_windows.html) → --- # Save file dialog | pywebview [#](https://pywebview.flowrl.com/3.7/examples/save_file_dialog.html#save-file-dialog) Save file dialog ======================================================================================================= Create a save file dialog after page content is loaded. import webview import time def save_file_dialog(window): time.sleep(5) result = window.create_file_dialog(webview.SAVE_DIALOG, directory='/', save_filename='test.file') print(result) if __name__ == '__main__': window = webview.create_window('Save file dialog', 'https://pywebview.flowrl.com/hello') webview.start(save_file_dialog, window) ← [Resize window](https://pywebview.flowrl.com/3.7/examples/resize_window.html) [Screens](https://pywebview.flowrl.com/3.7/examples/screens.html) → --- # Resize window | pywebview [#](https://pywebview.flowrl.com/3.7/examples/resize_window.html#resize-window) Resize window ============================================================================================== def resize(window): print('Window size is ({0}, {1})'.format(window.width, window.height)) sleep(2) window.resize(420, 420) print('Window size is ({0}, {1})'.format(window.width, window.height)) if __name__ == '__main__': window = webview.create_window('Resize window example', html='

Resize window

', width=800, height=600) webview.start(resize, window) ← [Open URL](https://pywebview.flowrl.com/3.7/examples/open_url.html) [Save file dialog](https://pywebview.flowrl.com/3.7/examples/save_file_dialog.html) → --- # Screens | pywebview [#](https://pywebview.flowrl.com/3.7/examples/screens.html#screens) Screens ============================================================================ Get available display information using `webview.screens` import webview def display_screen_info(): screens = webview.screens print('Available screens are: ' + str(screens)) if __name__ == '__main__': display_screen_info() # display screen info before starting app window = webview.create_window('Simple browser', 'https://pywebview.flowrl.com/hello') webview.start(display_screen_info) ← [Save file dialog](https://pywebview.flowrl.com/3.7/examples/save_file_dialog.html) [Toggle full-screen](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen.html) → --- # Toggle full-screen | pywebview [#](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen.html#toggle-full-screen) Toggle full-screen ============================================================================================================ Switch application window to a full-screen mode after five seconds. import webview import time def toggle_fullscreen(window): # wait a few seconds before toggle fullscreen: time.sleep(5) window.toggle_fullscreen() if __name__ == '__main__': window = webview.create_window('Full-screen window', 'https://pywebview.flowrl.com/hello') webview.start(toggle_fullscreen, window) ← [Screens](https://pywebview.flowrl.com/3.7/examples/screens.html) [Change user agent string](https://pywebview.flowrl.com/3.7/examples/user_agent.html) → --- # Change user agent string | pywebview [#](https://pywebview.flowrl.com/3.7/examples/user_agent.html#change-user-agent-string) Change user agent string ================================================================================================================= Change the user-agent of a window. EdgeHTML is not supported. import webview if __name__ == '__main__': webview.create_window('User Agent Test', 'https://pywebview.flowrl.com/hello') webview.start(user_agent='Custom user agent') ← [Toggle full-screen](https://pywebview.flowrl.com/3.7/examples/toggle_fullscreen.html) [Window title change](https://pywebview.flowrl.com/3.7/examples/window_title_change.html) → --- # Window title change | pywebview [#](https://pywebview.flowrl.com/3.7/examples/window_title_change.html#window-title-change) Window title change ================================================================================================================ Change window title every three seconds. import webview import time def change_title(window): """changes title every 3 seconds""" for i in range(1, 100): time.sleep(3) window.set_title('New Title #{}'.format(i)) if __name__ == '__main__': window = webview.create_window('Change title example', 'https://pywebview.flowrl.com/hello') webview.start(change_title, window) ← [Change user agent string](https://pywebview.flowrl.com/3.7/examples/user_agent.html) --- # Expose | pywebview [#](https://pywebview.flowrl.com/3.7/examples/expose.html#expose) Expose ========================================================================= To expose Python functions to the Javascript domain import webview def lol(): print('LOL') def wtf(): print('WTF') def echo(arg1, arg2, arg3): print(arg1) print(arg2) print(arg3) def expose(window): window.expose(echo) # expose a function during the runtime window.evaluate_js('pywebview.api.lol()') window.evaluate_js('pywebview.api.wtf()') window.evaluate_js('pywebview.api.echo(1, 2, 3)') if __name__ == '__main__': window = webview.create_window('JS Expose Example', html='

JS Expost') window.expose(lol, wtf) # expose functions beforehand webview.start(expose, window, debug=True) ---