PermissionError: [Errno 13] Permission denied (tested)

PermissionError: [Errno 13] Permission denied means the OS refused what your script asked for. We reproduced each common cause on Python 3.13.5 on Linux and tested a fix for each that doesn't involve sudo or chmod 777.

1. What raises it

import os, socket, stat

os.makedirs("reports", exist_ok=True)
with open("locked.txt", "w") as f:
    f.write("x")
os.chmod("locked.txt", stat.S_IRUSR)        # read-only for the owner

tests = {
    "open a directory":      lambda: open("reports"),
    "write read-only file":  lambda: open("locked.txt", "w"),
    "write to /etc":         lambda: open("/etc/myapp.conf", "w"),
    "bind port 80":          lambda: socket.socket().bind(("127.0.0.1", 80)),
}
for name, f in tests.items():
    try:
        f()
        print(f"{name}: ok")
    except OSError as e:
        print(f"{name}: {type(e).__name__}: {e}")
os.chmod("locked.txt", stat.S_IRUSR | stat.S_IWUSR)
open a directory: IsADirectoryError: [Errno 21] Is a directory: 'reports'
write read-only file: PermissionError: [Errno 13] Permission denied: 'locked.txt'
write to /etc: PermissionError: [Errno 13] Permission denied: '/etc/myapp.conf'
bind port 80: PermissionError: [Errno 13] Permission denied

Measured (Linux, as a normal user): writing to a file whose mode is read-only, creating a file in a directory you don't own (/etc), and binding a port below 1024 all raised PermissionError: [Errno 13] Permission denied. The port error has no filename in it, which is how you tell it apart. Opening a directory as a file raised IsADirectoryError: [Errno 21] here; on Windows the same mistake is widely reported as PermissionError: [Errno 13] instead (we didn't test Windows), so on Windows check first that the path isn't a folder.

2. Fixes

import os, stat

os.makedirs("reports", exist_ok=True)
path = os.path.join("reports", "summary.txt")   # a file inside the folder
with open(path, "w") as f:
    f.write("ok")
print(open(path).read())

print(os.access("/etc", os.W_OK), os.access(".", os.W_OK))
mode = stat.filemode(os.stat("/etc").st_mode)
print("/etc", mode, "owner uid", os.stat("/etc").st_uid, "me", os.getuid())
ok
False True
/etc drwxr-xr-x owner uid 0 me 1000

Frequently asked questions

What does PermissionError: [Errno 13] Permission denied mean?

The operating system refused the operation for your user. We measured it on Linux from writing a read-only file, creating a file in /etc, and binding port 80 as a normal user.

Why do I get Permission denied when opening a folder in Python?

You passed a directory to open(). On Linux we measured IsADirectoryError [Errno 21]; on Windows it's reported as PermissionError [Errno 13]. Join a filename onto the folder path.

Should I run my Python script with sudo to fix Errno 13?

Usually not. Write to a location you own instead; we measured os.access() showing /etc not writable and the current directory writable for a normal user.

Why can't Python bind to port 80?

Ports below 1024 need extra privileges on Linux. We measured PermissionError [Errno 13] with no filename; use 1024 or above, or a reverse proxy.

How do I check permissions from Python?

os.access(path, os.W_OK) for writability and stat.filemode(os.stat(path).st_mode) for the mode string; we measured both.

Written with AI assistance. Measured on 2026-10-09 with Python 3.13.5 on Linux as a non-root user: writing a chmod-read-only file, creating a file in /etc, binding 127.0.0.1:80, opening a directory with open(), and the os.access/stat checks. Every code block was run verbatim and its output pasted from that run. Windows behavior is noted from common reports, not tested. PlainHeaders is our extension; everything else here is built-in Python.