Five minutes from pip install to overwriting a value in another process.
pip install PyMemoryEditor(See Installation for the GUI app or installing from source.)
PyMemoryEditor exposes a single entry point: OpenProcess. You can target a
process by name or PID:
from PyMemoryEditor import OpenProcess
# By process name
process = OpenProcess(process_name="notepad.exe")
# Or by PID
process = OpenProcess(pid=1234)The recommended pattern is a with block — it closes the handle automatically:
with OpenProcess(process_name="notepad.exe") as process:
...By default, OpenProcess opens a read + write handle. No special permission
flag needed for the common case.
The building blocks are read_process_memory and write_process_memory.
For numeric types (int, float, bool) the size is inferred.
from PyMemoryEditor import OpenProcess
with OpenProcess(process_name="notepad.exe") as process:
address = 0x0005000C
# Read 4 bytes as an int
value = process.read_process_memory(address, int)
print("Current:", value)
# Write a new value (pass None to use the default size)
process.write_process_memory(address, int, None, value + 7)Strings and raw bytes need an explicit size:
name = process.read_process_memory(address, str, 32)You rarely know the address of a value up front — you find it by scanning.
search_by_value yields every address holding a given value:
with OpenProcess(process_name="game.exe") as process:
for address in process.search_by_value(int, 4, 100):
print(f"Found at 0x{address:X}")That's the same operation Cheat Engine performs in its First Scan button. See the searching guide for all eight comparison modes and the refine workflow.
The classic loop is:
- Scan for a value you can see (e.g. your health is
100) — you get back many candidate addresses. - Let the value change in the target (you take damage →
95). - Refine: keep only the addresses that now hold the new value. Repeat until one address remains — that's your value.
- Read, write or freeze it.
with OpenProcess(process_name="game.exe") as process:
# 1. First scan — every address currently holding 100.
candidates = list(process.search_by_value(int, 4, 100))
# 3. After the value drops to 95 in-game, keep only the matches that agree.
survivors = [
address
for address, value in process.search_by_addresses(int, 4, candidates)
if value == 95
]
# 4. Overwrite the survivors back to a high value.
for address in survivors:
process.write_process_memory(address, int, 4, 9999)For big targets, see the refine-scan workflow to cache the region map once.
The address you just found is useless next launch. The OS loads everything
somewhere new every time (ASLR), so 0x1FA3C140 today is garbage tomorrow.
The fix is a static pointer path: a chain that starts at a fixed location
inside a loaded module and dereferences its way to your value — so the same
recipe keeps working across restarts.
PyMemoryEditor finds these for you. scan_pointer_paths is a reverse pointer
scan (Cheat Engine's "Pointer scan"): give it the value's address right now,
and it discovers the static paths that resolve to it.
with OpenProcess(process_name="game.exe") as process:
# The value lives here this run (e.g. from search_by_value above).
for path in process.scan_pointer_paths(0x1FA3C140, max_depth=4):
print(path)
# "game.exe"+0x10F4F4 -> [+0x0] -> +0x158
print(hex(path.resolve(process)))Each result is a PointerPath carrying the module + offsets — the part that
survives a restart. Save the reliable ones and reuse them later:
with OpenProcess(process_name="game.exe") as process:
paths = list(process.scan_pointer_paths(0x1FA3C140, max_depth=4))
process.save_pointer_paths(paths, "health.json")
# ...next launch, the absolute address has changed but the path still works:
with OpenProcess(process_name="game.exe") as process:
survivors = process.rescan_pointer_paths("health.json", 0x2B7C0140)
pointer = survivors[0].rebase(process).to_pointer(process)
pointer.write(9999)See the pointer scan guide for tuning the scan
(max_depth, max_offset), the multi-run refine workflow, and intersecting
independent scans with compare_pointer_scans.
- 📖 User guide — every workflow, in depth.
- 🖥️ The bundled GUI app — same features, no code required.
- 📚 API reference — every public class and method.
- 🛟 Troubleshooting — common errors and how to fix them.
:class: warning
PyMemoryEditor talks to other processes through OS-level APIs. **Only point it
at processes you own or have explicit permission to inspect.**