python – Finding the user's "Downloads" folder

Question:

I already found this question that suggests to use os.path.expanduser(path) to get the user’s home directory.

I would like to achieve the same with the “Downloads” folder. I know that this is possible in C#, yet I’m new to Python and don’t know if this is possible here too, preferable platform-independent (Windows, Ubuntu).

I know that I just could do download_folder = os.path.expanduser("~")+"/Downloads/", yet (at least in Windows) it is possible to change the Default download folder.

Asked By: Markus Weninger

||

Answers:

Correctly locating Windows folders is somewhat of a chore in Python. According to answers covering Microsoft development technologies, such as this one, they should be obtained using the Vista Known Folder API. This API is not wrapped by the Python standard library (though there is an issue from 2008 requesting it), but one can use the ctypes module to access it anyway.

Adapting the above answer to use the folder id for downloads shown here and combining it with your existing Unix code should result in code that looks like this:

import os

if os.name == 'nt':
    import ctypes
    from ctypes import windll, wintypes
    from uuid import UUID

    # ctypes GUID copied from MSDN sample code
    class GUID(ctypes.Structure):
        _fields_ = [
            ("Data1", wintypes.DWORD),
            ("Data2", wintypes.WORD),
            ("Data3", wintypes.WORD),
            ("Data4", wintypes.BYTE * 8)
        ] 

        def __init__(self, uuidstr):
            uuid = UUID(uuidstr)
            ctypes.Structure.__init__(self)
            self.Data1, self.Data2, self.Data3, 
                self.Data4[0], self.Data4[1], rest = uuid.fields
            for i in range(2, 8):
                self.Data4[i] = rest>>(8-i-1)*8 & 0xff

    SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath
    SHGetKnownFolderPath.argtypes = [
        ctypes.POINTER(GUID), wintypes.DWORD,
        wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)
    ]

    def _get_known_folder_path(uuidstr):
        pathptr = ctypes.c_wchar_p()
        guid = GUID(uuidstr)
        if SHGetKnownFolderPath(ctypes.byref(guid), 0, 0, ctypes.byref(pathptr)):
            raise ctypes.WinError()
        return pathptr.value

    FOLDERID_Download = '{374DE290-123F-4565-9164-39C4925E467B}'

    def get_download_folder():
        return _get_known_folder_path(FOLDERID_Download)
else:
    def get_download_folder():
        home = os.path.expanduser("~")
        return os.path.join(home, "Downloads")

A more complete module for retrieving known folders from Python is available on github.

Answered By: user4815162342

This fairly simple solution (expanded from this reddit post) worked for me

import os

def get_download_path():
    """Returns the default downloads path for linux or windows"""
    if os.name == 'nt':
        import winreg
        sub_key = r'SOFTWAREMicrosoftWindowsCurrentVersionExplorerShell Folders'
        downloads_guid = '{374DE290-123F-4565-9164-39C4925E467B}'
        with winreg.OpenKey(winreg.HKEY_CURRENT_USER, sub_key) as key:
            location = winreg.QueryValueEx(key, downloads_guid)[0]
        return location
    else:
        return os.path.join(os.path.expanduser('~'), 'downloads')
  • The GUID can be obtained from Microsoft’s KNOWNFOLDERID docs
  • This can be expanded to work more generically other directories
Answered By: Alexander McFarlane

For python3+ mac or linux

from pathlib import Path
path_to_download_folder = str(os.path.join(Path.home(), "Downloads"))
Answered By: Jeff WR
from pathlib import Path
downloads_path = str(Path.home() / "Downloads")
Answered By: Shmidt

Some linux distributions localize the name of the Downloads folder. E.g. after changing my locale to zh_TW, the Downloads folder became /home/user/下載. The correct way on linux distributions (using xdg-utils from freedesktop.org) is to call xdg-user-dir:

import subprocess
# Copy windows part from other answers here
try:
    folder = subprocess.run(["xdg-user-dir", "DOWNLOAD"],
                            capture_output=True, text=True).stdout.strip("n")
except FileNotFoundError:  # if the command is missing
    import os.path
    folder = os.path.expanduser("~/Downloads")  # fallback

Note that the use of capture_output requires Python ≥3.7.
If you already use GLib or don’t mind adding more dependencies, see also
these approaches using packages.

Answered By: Dodezv

For python3 on windows try:

import os

folder = os.path.join(os.path.join(os.environ['USERPROFILE']), 'folder_name')
print(folder)
Answered By: Abdulkarim