Changelog¶
Unreleased (2026-10-03)¶
4.12.3 (2026-10-03)¶
Place files from
place_config_fileandplace_data_filein the first site directory for root on Unix withuse_site_for_root=Trueandmultipath=True, wherefind_config_fileandfind_data_filelook for them. PR #607
4.12.2 (2026-09-29)¶
Keep
os.pathsepinsite_applications_pathundermultipath=Trueon platforms with one applications directory. PR #604
4.12.1 (2026-09-28)¶
Avoid
PytestAssertRewriteWarningwhen importingplatformdirsbefore invoking pytest. PR #601
4.12.0 (2026-09-26)¶
Add
place_*_filemethods that return a file path under a user directory and create its missing parents with mode0o700. PR #585Add
find_<kind>_fileandfind_<kind>_filesto look up an existing file across the user and site directories of each kind that has aniter_<kind>_pathsmethod. PR #586Add
platformdirs.testing.isolated_dirs()and theplatformdirs_isolatedpytest fixture to resolve every directory under one test root. PR #590Emit
RuntimeDirWarningwhen the Unixuser_runtime_dir()falls back fromXDG_RUNTIME_DIR. PR #599Read
user_templates_dir,user_publicshare_diranduser_bin_diron Windows from their known folders. PR #587Create missing user app directories and their parents with mode
0700underensure_existson POSIX platforms. PR #588Raise
RuntimeErrorfor a Unix or macOS directory under the home when no home resolves, and read the password database for an emptyHOME. PR #589Skip an
XDG_RUNTIME_DIRor/run/user/<uid>that is not a private directory of the user, and reject a symlink or file as theruntime-<uid>fallback. PR #599Use the app container layout on iOS, such as
~/Library/Application Supportfor data. PR #600Document that a Homebrew Python puts the Homebrew prefix first in the macOS shared directories, with or without
multipath. PR #591Document that the macOS media directories honor the
XDG_*_DIRvariables. PR #592Document the
WIN_PD_OVERRIDE_COMMON_PROGRAMSvariable. PR #593Document
/usr/local/share/applicationsas the Linuxsite_applications_dirdefault. PR #594Correct the BSD
user_runtime_dirdefaults and describe the temporary directory fallback. PR #595Describe how platformdirs detects Android, finds the app folder and places the shared folders. PR #596
Document that Microsoft Store Python redirects only new files and folders under
AppData. PR #597Show how to load a font on Windows after copying it into
user_fonts_dir. PR #598
4.11.15 (2026-09-26)¶
Fix the pyjnius lookup of the Android app folder and media directories, which always failed. PR #580
Detect Android from
sys.getandroidapilevelwhenANDROID_DATAandANDROID_ROOTare unset. PR #581Put Android shared-storage directories under the current user’s /storage/emulated/<user id>, not user 0’s. PR #582
Move Android videos to
Moviesand the five non-standard media folders, such asDesktop, intoDocuments. PR #583
4.11.14 (2026-09-25)¶
With
ensure_exists, create a media directory such asuser_documents_dironly when the user set it through anXDG_*_DIRvariable oruser-dirs.dirs, and return a dangling symlink there instead of raisingFileExistsError. 4.11.13 also created the platform defaults, which filled headless home directories with folders such as~/Templatesand made a literal~directory whenHOMEwas unset. PR #561Ignore
$XDG_RUNTIME_DIRinuser_runtime_dirwhenuse_site_for_rootredirects root. PR #562Return
/storage/emulated/0/Downloadfrom the Androiduser_downloads_dir()fallback. PR #563Ignore
WIN_PD_OVERRIDE_*values that lack a drive or a root. PR #564Find the Android app folder for package names that start with
files. PR #565Reject an
appname,appauthororversionthat leaves the base directory when set after construction. PR #566Apply a changed
use_site_for_rooton the next read. PR #567Stop raising
UnicodeDecodeErroronuser-dirs.dirsbytes the locale encoding cannot decode. PR #568Drop a trailing
# commentfrom unquoteduser-dirs.dirsvalues. PR #569Treat empty Windows folder variables, such as
PUBLICorLOCALAPPDATA, as unset. PR #571Accept
roaminginuser_log_dir()anduser_log_path(). PR #572Detect Homebrew Python on macOS by its
opt/python*/Frameworkslayout. PR #573Keep colons in the Unix
site_cache_pathundermultipath. PR #574Return long Windows folder paths in place of 8.3 short names. PR #575
Create the Unix
runtime-<uid>temporary fallback with mode0700and reject one another user owns. PR #576Raise
RuntimeErrorin place of creating a literal~directory whenensure_existsfinds no home. PR #578Fix the Windows
user_preference_dirpath in the platform docs. PR #577Document that the macOS
user_state_dirandsite_state_dirignore theXDG_DATA_*variables. PR #579
4.11.13 (2026-09-25)¶
4.11.12 (2026-09-22)¶
Ignore relative paths in the XDG user directory environment variables, so
XDG_DOCUMENTS_DIR=Documentsno longer makesuser_documents_dir()and the other media directories return a path relative to the working directory. They now fall back to the platform default like the XDG Base Directory variables, and like the same keys read fromuser-dirs.dirs- by @darrenhuai. PR #554Copy nested directories in the versioned data migration recipe. PR #553
Exclude sphinx-llm 1.1.0 from documentation dependencies because its Markdown builder emits unknown-node warnings. PR #556
4.11.11 (2026-09-19)¶
Reject
appname,appauthorandversionvalues that leave the platform base directory (a..segment, a leading separator, a drive or a UNC share) withValueError, soensure_existscannot create directories outside it - by @Pitchfork-and-Torch. PR #552
4.11.10 (2026-09-18)¶
With
ensure_exists, thesite_*_dirandsite_*_pathproperties and theiter_*_dirsiterators only create the site directories they return or yield, instead of every entry in the site list - by @darrenhuai. PR #550
4.11.9 (2026-09-16)¶
Accept
multipathinsite_cache_dir()andsite_cache_path(). Without it, the function API could not return the Homebrew cache prefix thatsite_cache_diradds undermultipath- by @darrenhuai. PR #544Parse Unix
user-dirs.dirsline by line likexdg-user-dir. The INI parser raised on a repeated key or a line without=, and returned trailing comments and backslash escapes insideuser_documents_dir()and the other media directories. The last valid assignment now wins, and platformdirs unescapes the quoted value and ignores text after the closing quote - by @darrenhuai. PR #545Read
PUBLICbefore the home directory inuser_publicshare_dir()on Windows, so it no longer raisesRuntimeErrorwhenPUBLICis set and the home directory cannot be determined - by @emme1t. PR #546Raise
RuntimeErrorfromAndroiddirectories when the app folder cannot be found, instead ofTypeError: expected str, bytes or os.PathLike object, not NoneType- by @Str0k. PR #547
4.11.8 (2026-09-08)¶
Make
user_data_path(),user_config_path(),user_preference_path()anduser_applications_path()return the first site entry when root is redirected byuse_site_for_rootundermultipath, matching theirsite_*_pathtwins. They passed the whole joined list toPath, giving one unusable path such as/xdg/a/foo:/xdg/b/foo- by @darrenhuai. PR #538Ignore relative paths in XDG Base Directory environment variables and use the existing platform fallback. Relative entries in
$XDG_DATA_DIRSand$XDG_CONFIG_DIRSare skipped. PR #540Preserve literal percent signs in Unix
user-dirs.dirspaths, including100% complete,100%%and%(XDG_DESKTOP_DIR)s. Continue to expand$HOME. PR #542Use the base Python installation to locate Homebrew site directories on macOS, preserving shared data, config, cache and state paths inside virtual environments. PR #543
4.11.7 (2026-09-01)¶
4.11.6 (2026-09-01)¶
Give
user_bin_dir()anduser_bin_path()theuse_site_for_rootargument. They took none, so neither could reach the Unix redirect of root tosite_bin_dir(). PR #537
4.11.5 (2026-08-27)¶
Give
user_preference_dir()anduser_preference_path()the same arguments asuser_config_dir(). Added without arguments in PR #491, they could only return the unscoped base directory even though the property they wrap appends the app name and version. PR #531Make
site_applications_path()return the first entry whenmultipath=True, matchingsite_data_path(). On Unix and macOS it passed the whole$XDG_DATA_DIRSlist toPath, giving one unusable path such as/first/applications:/second/applications. PR #532Give
user_applications_dir(),user_applications_path(),site_applications_dir()andsite_applications_path()the app arguments. Android scopes both applications directories to the app, so without them the functions could only return the unscoped base directory there. On the two site functions they are keyword-only, keepingmultipathfirst positional as it has been since 4.9.0; the two user functions take their boolean options keyword-only. PR #534Correct the ordering note on the iterator methods.
use_site_for_rootdrops the user directory entirely, so the iterators are documented as yielding the most specific directory first rather than always yielding the user one. PR #533
4.11.4 (2026-08-24)¶
Stop the
iter_*_dirsmethods yielding the same directory twice when a site directory resolves to its user equivalent - PR #520 covered only Unix withuse_site_for_root. It also hititer_runtime_dirs()on Unix with$XDG_RUNTIME_DIRset, on Windows and macOS, and all six iterators on Android. PR #524Fix the config merging example in the how-to guide.
iter_config_pathsyields the user directory first, so theconfig.updateloop let the site defaults override the user’s config instead of the other way round. PR #529
4.11.3 (2026-08-13)¶
python -m platformdirsnow listsuser_desktop_dir(), which was missing from the properties it prints. PR #523Stop
site_data_dir(),site_config_dir()andsite_applications_dir()raisingIndexErroron Unix and macOS when$XDG_DATA_DIRSor$XDG_CONFIG_DIRSholds only separators and whitespace, such as":". These values now fall back to the platform defaults, and each entry is stripped of surrounding whitespace. PR #523
4.11.2 (2026-08-10)¶
Stop
iter_cache_dirs(),iter_state_dirs(),iter_log_dirs()anditer_runtime_dirs()yielding the same directory twice on Unix whenuse_site_for_rootis active - PR #469 fixed this for the config and data iterators only. On macOS,iter_cache_dirs()now yields the Homebrew and/Library/Cachesentries separately rather than oneos.pathsep-joined string whenmultipathis set. PR #520
4.11.1 (2026-08-07)¶
Fix
user_desktop_dir()on Windows builds withoutctypes.CSIDL_DESKTOPDIRECTORYappeared only in the ctypes lookup table, so the registry and environment variable resolvers raisedValueErrorfor it. PR #519
4.11.0 (2026-07-21)¶
Declare support for Python 3.15 and run the test suite against it, currently in beta. PR #512
4.10.1 (2026-07-18)¶
Stop leaking memory on repeated Windows folder lookups.
get_win_folder_via_ctypesdefined a freshctypesstructure on every call, and each one registered a pointer type that was never released; the resolver is now built once and reused. PR #507
4.10.0 (2026-05-28)¶
Add
user_publicshare_dir(),user_templates_dir(),user_fonts_dir(), anduser_preference_dir()PR #491Add
user_projects_dir()backed by$XDG_PROJECTS_DIRPR #490Return only the first path from
site_config_path()on macOS whenmultipathis set PR #488 - by @lphuc2250gma
4.9.6 (2026-04-09)¶
Fix macOS XDG variables leaking across
user_config_dir(),user_data_dir(), anduser_state_dir()when only some are set PR #473 - by @GoddesenAvoid duplicate site directories in Unix
iter_config_dirs()anditer_data_dirs()whenuse_site_for_rootis active PR #469 - by @viccie30
4.9.4 (2026-03-05)¶
Respect
XDG_CONFIG_HOMEwhen reading the user-dirs configuration PR #453 - by @bysiberCreate the directory in Android
user_log_dir()anduser_runtime_dir()whenensure_existsis set PR #452 - by @bysiber
4.9.2 (2026-02-16)¶
No user-facing changes
4.9.1 (2026-02-14)¶
No user-facing changes
4.9.0 (2026-02-14)¶
Use the correct runtime directory path on OpenBSD PR #440
4.8.0 (2026-02-14)¶
Add
use_site_for_rootto redirectuser_*_dirtosite_*_dirfor root on Unix PR #426Add
site_state_dir()for system-wide state PR #425Add
PLATFORMDIRS_*environment variable overrides for Windows folder resolution PR #427Add
WIN_PD_OVERRIDE_*environment variable overrides for Windows folder resolution PR #428Yield individual site directories from
iter_data_dirs()anditer_config_dirs()on macOS PR #429
4.7.1 (2026-02-13)¶
Avoid
FileNotFoundErroron Windows in sandboxed environments PR #422
4.7.0 (2026-02-12)¶
4.6.0 (2026-02-12)¶
Honor XDG environment variables on macOS PR #375 - by @Czaki
Fix
site_cache_dir()documentation PR #402 - by @brianhelbaFix an outdated link and correct a function docstring PR #398 - by @joclement
4.5.1 (2025-12-05)¶
Fix no-ctypes fallback on Windows PR #403 - by @youknowone
4.5.0 (2025-10-08)¶
Drop support for Python 3.9 PR #389
Update Windows file paths in README PR #385 - by @ParadaCarleton
4.4.0 (2025-08-26)¶
4.3.8 (2025-05-07)¶
Add missing examples and fix example order in README PR #355 - by @gene1wood
4.3.7 (2025-03-19)¶
4.3.6 (2024-09-17)¶
No user-facing changes
4.3.5 (2024-09-17)¶
No user-facing changes
4.3.4 (2024-09-17)¶
No user-facing changes
4.3.3 (2024-09-13)¶
No user-facing changes
4.3.2 (2024-09-08)¶
Fix multi-path returned from
_pathmethods on macOS PR #299 - by @matthewhughes934
4.3.1 (2024-09-07)¶
No user-facing changes
4.3.0 (2024-09-07)¶
Make
PlatformDirsusable as a mypy superclass without breaking other type checkers PR #295 - by @AvasamAdd support for Python 3.13 PR #289 - by @edgarrmondragon
4.2.2 (2024-05-15)¶
Fix Android detection when
python-for-androidis present PR #277 - by @tmolitor-stud-tu
4.2.1 (2024-04-23)¶
Allow working without ctypes PR #275 - by @youknowone
4.2.0 (2024-01-31)¶
Add convenience methods to iterate over both user and site dirs and paths PR #258 - by @SpaceshipOperations
Fix two typos referencing
XDG_DATA_DIRPR #256 - by @Freed-Wu
4.1.0 (2023-12-04)¶
Fix Linux
user_log_dir()example in README PR #245 - by @dbohdan
4.0.0 (2023-11-10)¶
Revert
site_cache_dir()on UNIX to/var/cacheinstead of/var/tmpPR #239 - by @andersk
3.11.0 (2023-10-02)¶
Detect Homebrew-installed software on macOS PR #232 - by @singingwolfboy
3.10.0 (2023-07-29)¶
Add
site_runtime_dir()PR #212 - by @kemzeb
3.9.1 (2023-07-15)¶
Optionally create the opinionated
logsubdirectory inuser_log_dir()on Unix PR #208 - by @kemzeb
3.9.0 (2023-07-15)¶
Add
user_desktop_dir()anduser_desktop_path()PR #200 - by @lukacat10
3.8.1 (2023-07-06)¶
Provide a fallback for
user_runtime_dir()on BSD PR #201 - by @RayyanAnsari
3.8.0 (2023-06-22)¶
No user-facing changes
3.7.0 (2023-06-20)¶
Return
/var/run/user/$uidfromuser_runtime_dir()on *BSD PR #194 - by @kemzeb
3.6.0 (2023-06-18)¶
Add
user_downloads_dir()PR #192 - by @cofiem
3.5.3 (2023-06-09)¶
Add support for Python 3.12
3.5.2 (2023-06-09)¶
No user-facing changes
3.5.1 (2023-05-11)¶
Define
getuidon all non-Windows platforms souser_runtime_dir()works beyond Linux PR #183
3.5.0 (2023-04-27)¶
Add
user_music_dir()PR #173 - by @kemzeb
3.4.0 (2023-04-26)¶
Add
user_videos_dir()PR #169 - by @kemzeb
3.3.0 (2023-04-25)¶
Add
user_pictures_dir()PR #167 - by @kemzeb
3.2.0 (2023-03-25)¶
3.1.1 (2023-03-10)¶
Point
site_cache_dir()at/var/tmpinstead of write-protected/var/cacheon Unix PR #148 - by @efiop
3.1.0 (2023-03-03)¶
Add
site_cache_dir()PR #145 - by @efiop
3.0.0 (2023-02-06)¶
BREAKING Point macOS
user_config_dir()andsite_config_dir()at*/Library/Application Supportto mirror the data dirs, and drop the trailing slash fromuser_config_dir()anduser_data_dir()PR #137 - by @ThomasWaldmann
2.6.2 (2022-12-28)¶
2.6.1 (2022-12-29)¶
2.6.0 (2022-12-06)¶
Point
user_log_dir()atuser_state_dir()on Linux per the XDG spec PR #108 - by @lordwelch
2.5.4 (2022-11-12)¶
No user-facing changes
2.5.3 (2022-11-06)¶
2.5.2 (2022-04-18)¶
Treat Android shells as Unix PR #72
2.5.1 (2022-02-19)¶
Work out of the box under Nuitka standalone builds PR #68
2.5.0 (2022-02-09)¶
Support the Termux subsystem PR #63 - by @YariKartoshe4ka
2.4.1 (2021-12-26)¶
BREAKING Drop Python 3.6 support PR #52
2.4.0 (2021-09-25)¶
Add
user_documents_dir()PR #39 - by @JuneStepp
2.3.0 (2021-08-30)¶
Add
user_runtime_dir()for$XDG_RUNTIME_DIRPR #37 - by @whonore
2.2.0 (2021-07-29)¶
2.1.0 (2021-07-25)¶
Add
pathlib.Path-returning*_pathAPI alongside the string variants PR #27 - by @paprAdd Android support PR #18
Add type annotations PR #20 - by @domdfcoding
BREAKING Drop Python 2.7 and 3.5 support PR #14 - by @domdfcoding
2.0.2 (2021-07-13)¶
No user-facing changes
2.0.0 (2021-07-12)¶
BREAKING Rename
appdirstoplatformdirsas part of the friendly forkBREAKING Remove support for end-of-life Pythons 2.6, 3.2, and 3.3
BREAKING Correct the config directory on macOS
Add support for Python 3.7, 3.8, and 3.9