PyPython example

How to check if a key exists in a dictionary in Python

5 min read▶ Runs in an isolated hosted runtimeUpdated Jul 2026

Quick answer

Use the in operator: if "port" in config:. It tests keys (never values), returns a plain True/False, and can't raise. Writing key in config.keys() does exactly the same thing with an extra step — drop the .keys().

Indexing a dict with a key it doesn't have raises KeyError, so you need a way to ask first — or a way to read that tolerates a miss. The four options below split into two camps: in and try/except answer does this key exist?, while get() and setdefault() hand you a value either way. Each example runs on this page — hit Run, then edit and run it again.

1The in operatorRecommended

key in d is a single hash lookup — O(1), regardless of how big the dict is — and it's the clearest way to say what you mean. Use not in for the inverse.

key_exists.py

Output

Two things to internalise. First, in checks keys — the fourth line prints False even though "localhost" is right there as a value. To search values you need value in d.values(), which is a linear O(n) scan. Second, key in d.keys() is not wrong, just redundant: it builds a view object and then does the same lookup. Python 2's d.has_key() was removed in Python 3 — in replaced it.

2dict.get() with a default

When you don't care whether the key is there, only what value to use, skip the check and call get(). With one argument it returns None for a missing key; with two it returns your fallback.

get_default.py

Output

The last line prints {'host': 'localhost', 'port': 8080}: reading a missing key with get() does not add it. That's the difference between get() and setdefault() in section 6. The default argument is evaluated eagerly, so avoid d.get(k, expensive()) — call it only in the miss branch instead.

3The gotcha: keys with falsy values

This is the bug that actually bites people: if d.get(key): is not the same test as if key in d:. get() hands back the value, and 0, "", None, [] and False are all falsy — so a key that exists gets treated as missing.

falsy_trap.py

Output

Three keys exist and every one of them is falsy — the truthy column is False for all four rows, so a truthiness test can't tell "retries": 0 apart from a key that was never set. If you need existence, use in. If you need "present and not None", be explicit: d.get(key) is not None.

4try/except KeyError (EAFP)

Python leans EAFPeasier to ask forgiveness than permission. Index the dict and catch KeyError. The exception object carries the offending key, which makes for good error messages.

eafp.py

Output

Note the quotes in missing key: 'timeout'KeyError reprs the key, so a string key shows up quoted. Reach for this when the key is almost always present (one lookup on the happy path instead of the two an in check plus an index costs) or when a miss is a genuine error you want to log or re-raise. For a plain fallback value, get() is shorter and clearer.

5Which should you use?

MethodReturns the valueOn a missing keyBest for
key in dNoReturns FalseAny existence check
d.get(key, default)YesReturns the defaultReading with a fallback
d[key] + try/exceptYesRaises KeyErrorKeys that should be there
d.setdefault(key, default)YesInserts the defaultCheck and insert in one step
value in d.values()NoScans O(n)Finding a value, not a key

6Common variation: check and insert

When a miss should create the entry, setdefault() collapses the check and the write into one call: it returns the existing value if the key is there, otherwise inserts your default and returns that. For the grouping pattern, collections.defaultdict is the same idea with the default baked in.

check_and_insert.py

Output

The catch with defaultdict is that reading a missing key creates it, so d[k] can never tell you a key is absent — use k in d on a defaultdict, which does not insert. Dicts preserve insertion order in Python 3.7+, so the grouped output comes out python first, exactly in the order the keys were first seen.

Frequently asked questions

Is `key in d` the same as `key in d.keys()`?

They give the same answer, but key in d.keys() builds a view object first and then does the same hash lookup, so it is pure overhead. Use key in d. Python 2’s d.has_key() was removed in Python 3 — in is its replacement.

How do I check if a value exists in a dictionary?

Use value in d.values(). Unlike a key check it is a linear O(n) scan, because dicts are only indexed by key. If you need repeated value lookups, build a reverse mapping or a set(d.values()) once and test against that.

Why does `if d.get(key):` say a key is missing when it exists?

Because get() returns the value, and 0, "", None, [] and False are all falsy — so if d.get(key): is false for a key that really is present. Use if key in d: for existence, or if d.get(key) is not None: if you specifically mean "present and not None".

How do I check if a nested key exists?

Chain get() with an empty-dict default so each level is safe: data.get("db", {}).get("port", 5432), or "host" in data.get("db", {}). For deeper or mixed structures, a try/except (KeyError, TypeError) around the direct data["db"]["port"] index is easier to read.