I'm working on porting the Ren'Py framework to the HTML5 web browser - so you can publish Visual Novel games online :)

Donate and help the development go faster!

Test it!

Current version: 7.3.5/red-2019-10-18
The Question - Web Edition Tutorial - Web Edition
(Shitf+O for dev console, F3 for perfs)

Also available for testing at:


Stable version: RenPyWeb is now officially included in Ren'Py and can be run from the Launcher! Ren'Py download
Leave feedback!

RED (RenPyWeb Early Downloads): as a thank you for my patrons, I also bundle Ren'Py + latest RenPyWeb improvements/fixes such as better perfs
(so you don't have to wait for the next official Ren'Py release)
RenPyWeb Early Downloads

Source code: check the official Ren'Py repository at:
Contributions much welcome :)
Ren'Py nightlies provide the development version of Ren'Py and RenPyWeb (pending review and build delays)

Another project: I also develop the Ren'Py Translator ToolKit for PO files - give it a try :)


Feedback welcome!
Patreon - e-mail - Lemma Soft Forums - itch.io - newgrounds


Here are a few public games that run on RenPyWeb.

This list of games is not curated, use at your own risk.

Let me know if you made a web version of your game :)


RenPyWeb's goal is to run your game without additional work. However the web is a very different environment so here are a couple things to know.

Size: this is the web, so things need to be light. Think Flash games. Think metered mobile plan.
In addition, RenPyWeb currently needs to download the full game before playing. ~100MB tops, or your players will complain, because they have to download that everytime they play before it starts! Plus browsers only cache files up to ~50MB.
I've been meaning to work on background/on-demand resources download and improve this (see
roadmap), I need to get enough time :)
Even with that, large assets will mean large downloads, so think light and optimize your game.
Solutions include: using layered images, making a lower-res or lossy/jpg version, optimizing images (.webp format, pngquant...), using flat-shading, dropping (some) audio, dropping videos (not supported yet), splitting in chapters, etc.
Note on Python environment: the RenPyWeb Python environment is minimal for size reasons. You may ship additional Python modules in your Ren'Py game. Alternatively you can try placing additional .pyo files (e.g. from your Ren'Py SDK) in /lib/python2.7 in your game.zip.

Speed: browser apps are pretty different than desktop/mobile apps, and fitting Ren'Py currently requires a speed compromise (gory details).
Things are improving, for a first boost see RED.

Audio glitches: this is due to Speed, see entry above for a fix.

Savegame: user savegames are linked to the webpage domain.
Ideally, provide a stable (sub)domain - like this page.
Some hosts may change your domain on new upload, causing previous savegames to become unreachable.
In addition, a game can read/modify savegames from other games hosted at the same domain. Ren'Py will ignore them, but a malicous game developer could do bad things.
For itch.io (hosts at XXX.ssl.hwcdn.net, previously at commondatastorage.googleapis.com) it's not clear how often the domain may change: see How to save data? and HTML5 game : Save data locally.
For newgrounds all games are hosted at uploads.ungrounded.net so other games could read your player's data. NG passes the user identity and session as querystring, though that only helps for logged-in users.
Last, if the user blocked 3rd-party cookies (by default in Debian Chromium) and running the game in a iframe (most web game hosts), savegames are lost on reload (discuss).
In doubt, remind players to export their savegames from RenPyWeb's top-left menu.

Memory/RAM: memory may be scarse, especially on mobile browsers.
To optimize memory usage, make sure config.cache_surfaces is set to False, and/or provide a lower-res version of your game (less virtual filesystem, cache and video memory required for graphics).
Note: since the browser can't access the player's disk, game.zip is currently extracted in RAM. (In the future we may remove images and sounds from game.zip, storing them separately on the server, hence eventually in the browser cache and/or IndexedDB, hence on the player's disk.)

Network: browser outgoing connections are secured by Same-origin policy.
In addition, the browser can only perform XHR and WebSocket (i.e. no direct TCP/IP or UDP/IP connections).
Last, it is dangerous if your game waits on a connection (even in native Ren'Py): any network issue (unplugged cable, out-of-reach WiFi, etc.) will freeze the game for minutes and the user won't even be able to save. Usually this can be worked-around with threads (e.g. Renpytom's analytics) but they are currently not available in the browser.

I wrote an asyncrequest.rpy so you can make asynchronous HTTP requests in both native and web versions, based on urllib2 and XMLHttpRequest respectively. There's an example usage at the end.

You can also experiment with WebSockets, which are initiated transparently when you make a TCP/IP connection from Python, but you need a specific server, or a service proxy (cf. Introduction to Emscripten Sockets) on the developer's server side.

Dev notes: there are Emscripten-specific helpers (which I didn't expose yet in RenPyWeb/python-emscripten).
emscripten_async_wget is asynchronous.
emscripten_wget is synchronous and requires -s ASYNCIFY=1 (and an appropriate WHITELIST at compile-time).
emscripten_fetch has similar features, synchronous mode is restricted to web Workers.

Mobile: mobile browsers are a bit behind when it comes to web technologies, and RenPyWeb currently may not work well on these.
Another issue is the lack of text input, which is common to mobile games in general; if you require the user to enter text, you may need to implement a virtual keyboard in Ren'Py itself. If you know a technique to display use the virtual keyboard in mobile games, please share :)

Presplash: add a web-presplash.png or web-presplash.jpg at the top-level of your game (above, not inside, your game directory, along with android-presplash.*).

Screen Variants (Ren'Py doc): the new "web" variant is always set, the "mobile" variant is set on mobile browsers, "touch" is set in mobile devices with touch support, "large/medium/small" is set on mobile depending on screen size and "large" is always set on pc, "pc/phone/tv/android/ios" is NOT defined as this is reserved for direct, non-browser access to the device.

Web hosts format: zip all the files from the build directory (so index.html, game.zip, index.wasm.gz, etc. are at the top-level of your zip archive).
for newgrounds, edit your game again and tick HTML5 Archive (zip) > Edit Properties > Touchscreen friendly otherwise it will be marked as incompatible with mobile.
for itch.io, tick This file will be played in the browser when uploading.

Play offline: browsers now have all kinds of security limitations, and require that you run your game through a local webserver (the Ren'Py launcher runs one automatically for you).
Note: just double-clicking on index.html used to work with Firefox, but not anymore with version 68; it didn't keep saved games anyway.
Note: some other web game engines run offline to some extent but they use different web technologies with different limitations.

Invalidating browser cache on game update: when releasing a new version of your game, I suggest you either change the path where you upload the new version (game hosts usually do that), or control cache (see the provided htaccess.txt). Otherwise, the browser may mix cached and non-cached versions, causing errors.

Including more than one game: you can select alternate games through ?game=xxx.zip
(renpy.beuc.net/play/?game=https://somewhere-else.net/game.zip is blocked so a user cannot be tricked into running a malicious game)

Change game.zip extension: apparently cloudflare does not cache .zip files in their basic plan, and maybe you need to change the file extension for whatever reasons.
If you cannot make them change, you can rename game.zip to game.xyz and set DEFAULT_GAME_FILENAME accordingly in your index.html.
(alternatively you can start your game by adding ?game=game.xyz as explained in Including more than one game.)


(in no definite order)

Status reports

2019 week 41 (2019-10-13)

2019 week 40 (2019-10-06)

2019 week 39 (2019-09-29) - nearly a year!

2019 week 38 (2019-09-22)

2019 week 37 (2019-09-15)

2019 week 36 (2019-09-08)

2019 week 35 (2019-09-01)

2019 week 34 (2019-08-25)

Emscripten upgrade (1.38.32->1.38.37, with SDL port 2.0.7->2.0.9; final target: 1.38.42)

2019 week 33 (2019-08-18)

2019 week 32 (2019-08-11)

2019 week 31 (2019-08-04)

2019 week 30 (2019-07-28)

2019 week 29 (2019-07-21)

2019 week 28 (2019-07-14)

2019 week 27 (2019-07-07)

2019 week 26 (2019-06-30) [renpy-]

2019 week 25 (2019-06-23)

2019 week 24 (2019-06-16) [renpy-]

2019 week 23 (2019-06-09)

2019 week 22 (2019-06-02)

2019 week 21 (2019-05-26)

2019 week 20 (2019-05-19)

2019 week 19 (2019-05-12)

2019 week 18 (2019-05-05)

2019 week 17 (2019-04-28)

2019 week 16 (2019-04-21)

2019 week 15 (2019-04-14)

2019 week 14 (2019-04-07)

2019 week 13 (2019-03-31)

2019 week 12 (2019-03-25)

2019 week 9 (2019-03-03)

2019 week 8 (2019-02-24)

2019 week 6 (2019-02-10)

2019 week 5 (2019-02-03)

2019 week 4 (2019-01-27)

2019 week 3 (2019-01-20)

2018 week 52 (2018-12-30)

2018 week 50 (2018-12-16)

2018 week 49 (2018-12-09)

2018 week 48 (2018-12-02)

2018 week 47 (2018-11-25)

2018 week 46 (2018-11-18)

2018 week 45 (2018-11-11)

2018 week 44 (2018-11-04)

2018 week 43 (2018-10-29)

2018 week 42 (2018-10-21)

2018 week 41 (2018-10-14)

2018 week 40 (2018-10-07)

2018 week 39 (2018-09-30)