32blogby StudioMitsu
renpy6 min read

Can You Use Non-ASCII Filenames in Ren'Py?

Why non-ASCII filenames work in Ren'Py 8.5, the distribution risks they create, and the safe ASCII alias pattern. Includes Python 3 Unicode fundamentals.

renpyvisual-novelgame-devpython
On this page

While building a game in Ren'Py, you might notice something.

renpy
play music "戦闘BGM.ogg"

A Japanese filename. No errors. It just works.

You might think "Great, I'll use native-language filenames for easier management." But the short answer is: don't. This guide explains why it works, why it's risky, and what to do instead.

The Short Answer: It Works, But It's Unofficial

In Ren'Py 8.5.2, using non-ASCII characters (Japanese, Chinese, Korean, accented Latin, etc.) in image, audio, and video filenames works on most systems.

However, this is not an officially supported feature. Tom Rothamel (PyTom), Ren'Py's creator, has consistently stated on the Lemma Soft Forums:

Use ASCII in all filesystem object names. This makes distribution and cross-platform compatibility significantly easier.

The official documentation contains no statement that Unicode filenames are supported.

Why It Works: Python 3 Unicode Handling

Understanding why non-ASCII filenames work requires a quick history lesson about Python.

The Python 2 Era (Ren'Py 6.x / 7.x)

In Python 2, strings were byte sequences (str = bytes) by default. To handle non-ASCII text, you needed the u"" prefix to explicitly create a Unicode string.

python
# Python 2 — this is a byte string
"battle_bgm.ogg"

# Python 2 — this is a Unicode string
u"戦闘BGM.ogg"

In Ren'Py 6.x, audio file handling passed filenames to C functions as char*, causing UnicodeEncodeError crashes with non-ASCII names. This was fixed in 2014, but Python 2's string handling remained fundamentally limited.

The Python 3 Era (Ren'Py 8.x)

In Python 3, strings are Unicode by default.

python
# Python 3 — this is already Unicode
"戦闘BGM.ogg"

The u"" prefix is no longer needed. Every string literal is natively Unicode. Ren'Py 8.x runs on Python 3.12, so the encoding issues from the Python 2 era simply don't occur at the string level.

In other words, Ren'Py didn't add non-ASCII filename support — Python 3 made Unicode the default, and filenames started working as a consequence.

Why It's Risky: Three Ways Distribution Breaks

Working on your dev machine and working on a player's machine are two different things. Non-ASCII filenames hit three landmines during distribution.

Case 1: macOS Unicode Normalization

macOS's legacy filesystem HFS+ stores filenames in NFD (decomposed form). Windows and Linux typically use NFC (composed form).

For example, the Japanese character "が" has two internal representations:

FormRepresentationDescription
NFC (1 character)Composed. Standard on Windows/Linux
NFD + (2 characters)Decomposed. Standard on macOS HFS+

A file stored as NFC 戦闘BGM.ogg in a ZIP gets extracted as NFD 戦闘BGM.ogg on macOS. When Ren'Py searches for the NFC version, the file isn't found.

This exact problem was reported in the commercial Ren'Py game "WORLD END ECONOMiCA," where a Japanese filename 飛び_右下.png failed to load on macOS.

Case 2: ZIP Filename Encoding Mismatch

Ren'Py's build system produces ZIP and tar.bz2 distribution files. The ZIP format has no standardized filename encoding.

Python 3's zipfile module sets the UTF-8 flag (bit 11) when writing, but older extraction tools and some Windows Explorer versions ignore this flag. The result: garbled filenames and a game that won't start.

Case 3: Web and Android Builds Are Untested

Ren'Py supports web browser builds (Emscripten/WebAssembly) and Android APK builds. However, there is no official confirmation that non-ASCII filenames work correctly on these platforms. Web builds have additional concerns around HTTP URL encoding interactions.

The Safe Alternative: ASCII Filenames + Aliases

Keep filenames in ASCII and use define aliases for readability in your scripts.

Audio Files

renpy
# Files in audio/ use ASCII names
# audio/battle_bgm.ogg
# audio/village_theme.ogg
# audio/rain_ambient.ogg

define audio.battle_bgm = "audio/battle_bgm.ogg"
define audio.village_theme = "audio/village_theme.ogg"
define audio.rain_ambient = "audio/rain_ambient.ogg"

label start:
    play music battle_bgm
    play sound rain_ambient

Creating aliases in the audio namespace with define means you never need to write file paths in play music statements. The variable name tells you what the audio is, so readability isn't a problem.

Image Files

Ren'Py's automatic image detection maps space-separated filenames to image names (see the image display docs).

text
images/
├── bg forest.png      → scene bg forest
├── bg castle.png      → scene bg castle
├── eileen happy.png   → show eileen happy
└── eileen sad.png     → show eileen sad

For manual definitions, stick to ASCII as well.

renpy
image bg forest = "images/bg_forest.png"
image bg castle = "images/bg_castle.png"

Naming Conventions

Establishing project-wide rules keeps things manageable as your file count grows.

text
# Audio
audio/{type}_{description}.ogg
  audio/bgm_battle.ogg
  audio/sfx_sword_slash.ogg
  audio/amb_rain.ogg

# Backgrounds
images/bg {location}.png
  images/bg forest.png
  images/bg castle.png

# Characters
images/{name} {expression}.png
  images/eileen happy.png
  images/eileen angry.png

Wrapping Up

  • Does it work? — Non-ASCII filenames work in Ren'Py 8.5.2 on most systems
  • Why? — Python 3's native Unicode string handling. Not an official Ren'Py feature
  • Risks — macOS NFD normalization, ZIP encoding mismatches, untested Web/Android builds. Distribution can break silently
  • Recommendation — ASCII filenames + define aliases are safe and practical

For Ren'Py basics, see the getting started guide. For save-safe stat system design, see the stat management guide.

Official resources: