Fundamentals

Fix the 401 Unauthorized Error in OpenAI Python

This guide shows you how to fix the OpenAI 401 Unauthorized error in Python in under ten minutes. A 401 always means one thing: the server could not confirm who you are. Your request arrived, but the API key it carried was missing, mistyped, wrong, expired, or aimed at the wrong account. The good news is that the model never ran, so a 401 costs you nothing and is safe to retry once fixed.

We will look at the exact message you see, then walk through numbered fixes. Each fix has runnable Python 3.10+ you can paste and run. If you are brand new to keys and requests, read Understanding LLM APIs first, since this page assumes you already have a key and the openai SDK installed.

The exact error you see

When the key fails, the openai SDK raises an AuthenticationError and prints something close to this:

openai.AuthenticationError: Error code: 401 - {'error': {'message': 'Incorrect
API key provided: sk-abcd****. You can find your API key at
https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error',
'param': None, 'code': 'invalid_api_key'}}

The key signal is the number 401 and the class name AuthenticationError. If you instead see 429, that is a rate or quota problem covered in Fix the 429 Rate-Limit Error in Python, not an auth problem. Confirm you really have a 401 before applying these fixes.

Prerequisites

You only need what differs from the parent section: the openai SDK, python-dotenv to load your key, and a recent Python. Pin versions so your results match this guide.

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install "openai>=1.40" "python-dotenv>=1.0"

Create a .env file next to your script with your key on one line, no quotes and no spaces:

OPENAI_API_KEY=sk-your-real-key-goes-here

Add .env to your .gitignore so the key never lands in version control. A leaked key can be used by strangers and billed to you.

echo ".env" >> .gitignore

Fix 1 — Confirm the key is actually loaded

The most common cause of a 401 is that your program never read the key at all. A .env file does nothing by itself; you must load it. This check prints the key's length and a masked prefix so you can see whether it arrived without ever exposing the full secret.

import os
from dotenv import load_dotenv

load_dotenv()  # reads .env from the current working directory

key = os.environ.get("OPENAI_API_KEY")
if not key:
    print("No key found. .env not loaded, or the variable name is wrong.")
else:
    print(f"Key loaded: length {len(key)}, starts with {key[:6]}...")

A healthy key prints a length in the dozens and starts with sk-. If you see "No key found", the .env file is in a different folder than where you run the script, or the variable is misnamed. Run the script from the folder that holds .env, or pass an explicit path: load_dotenv("/full/path/to/.env").

Fix 2 — Catch the error and read its details

Wrap your call so the program tells you precisely what went wrong instead of crashing. The openai SDK gives the status code and an exact message you can act on.

import os
from dotenv import load_dotenv
from openai import OpenAI, AuthenticationError

load_dotenv()
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

try:
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": "ping"}],
    )
    print(resp.choices[0].message.content)
except AuthenticationError as err:
    print(f"401 auth failed (status {err.status_code}): {err.message}")

Read the printed message. Phrases like "Incorrect API key provided" point to a wrong or mistyped key (Fix 3). Phrases mentioning an organization or project point to an account mismatch (Fix 4).

Fix 3 — Check the key is correct, current, and clean

A 401 with "Incorrect API key" means the string is wrong. Three things cause this: a typo, a key that was revoked or regenerated, or hidden characters copied along with the key. This check catches the hidden-character case, which is easy to miss.

import os
from dotenv import load_dotenv

load_dotenv()
key = os.environ.get("OPENAI_API_KEY", "")

problems = []
if not key.startswith("sk-"):
    problems.append("key does not start with 'sk-'")
if key != key.strip():
    problems.append("key has leading or trailing whitespace")
if '"' in key or "'" in key:
    problems.append("key contains quote characters from the .env file")

print("Problems:" if problems else "Key format looks clean.")
for p in problems:
    print(" -", p)

If the format looks clean but the call still fails, the key itself is likely wrong or revoked. Open the API keys page in your OpenAI account, create a fresh key, and paste it into .env with no surrounding quotes. Never wrap the value in quotes in a .env file; python-dotenv keeps them as part of the string.

Fix 4 — Match the organization, project, and provider

A correctly typed, current key can still return 401 if it points at the wrong place. This happens when your account has more than one organization or project, or when base_url is aimed at a different provider whose servers reject an OpenAI key.

import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()

client = OpenAI(
    api_key=os.environ["OPENAI_API_KEY"],
    organization=os.environ.get("OPENAI_ORG_ID"),    # optional, set only if needed
    project=os.environ.get("OPENAI_PROJECT_ID"),     # optional, set only if needed
    base_url="https://api.openai.com/v1",            # the real OpenAI endpoint
)
print("Talking to:", client.base_url)

Confirm base_url reads https://api.openai.com/v1. If you earlier set it to a free or third-party gateway, an OpenAI key will be rejected there. Mixing providers is a frequent trap when following tutorials that compare services such as Groq vs OpenRouter Free Tier; each provider needs its own matching key. Likewise, only set organization and project if your key belongs to that exact org and project. A mismatched org or project ID is just as fatal as a bad key.

Fix 5 — Run a minimal working call

Once the checks pass, prove the fix with the smallest possible request. A clean reply here means your authentication is fully working.

import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Reply with the single word: working"}],
)
print(resp.choices[0].message.content)

If this prints working, the 401 is solved. Build the rest of your program on top of this proven client.

Cause and fix quick reference

CauseFix
.env never loadedCall load_dotenv() before reading the key; run from the folder holding .env
Wrong variable nameUse OPENAI_API_KEY exactly, in both .env and os.environ
Key mistyped or has quotes/spacesRe-paste cleanly with no quotes; check key.strip() and the sk- prefix
Key revoked or expiredGenerate a new key in your OpenAI account and update .env
Wrong org or projectSet organization and project to match the key, or remove them
base_url points at another providerReset base_url to https://api.openai.com/v1 and use that provider's own key

Troubleshooting

  1. KeyError: 'OPENAI_API_KEY' — The variable is not in the environment. Cause: load_dotenv() ran from the wrong folder, or the .env line is misspelled. Fix: run the script from the folder containing .env, or load an absolute path with load_dotenv("/full/path/.env").
  2. 401 only when running from cron or a server — The shell that loads .env differs from the one your job uses. Cause: a hardcoded environment variable on the machine overrides .env. Fix: add load_dotenv(override=True) so the file wins, or unset the stale variable with unset OPENAI_API_KEY.
  3. Key works in the browser playground but not in code — You copied a session token, not an API key, or the wrong account's key. Fix: copy the key from the API keys page (it starts with sk-) and confirm you are signed into the right account.
  4. 401 right after it worked yesterday — The key was rotated or revoked, or a free trial expired. Fix: generate a new key and confirm your account has active billing or remaining quota.

Still failing? Final checklist

Work down this list and the 401 almost always falls:

  • The key prints a non-zero length and a sk- prefix at runtime.
  • .env has no quotes, no trailing spaces, and uses the name OPENAI_API_KEY.
  • You ran the script from the folder that holds .env, or loaded an absolute path.
  • The key is current: not revoked, not from an expired trial.
  • base_url is https://api.openai.com/v1, not a third-party gateway.
  • Any organization or project value matches the key, or is left unset.
  • Your account has billing set up or free quota remaining.

When to use this vs. alternatives

Back to Understanding LLM APIs.