Quick Startο
Five minutes from pip install to overwriting a value in another process.
1. Open a processο
PyMemoryEditor exposes a single entry point: OpenProcess. Target a
process by name or PID:
from PyMemoryEditor import OpenProcess
# By process name
process = OpenProcess(name="notepad.exe")
# Or by PID
process = OpenProcess(pid=1234)
The recommended pattern is a with block β it closes the handle automatically:
with OpenProcess(name="notepad.exe") as process:
...
2. Read and write a valueο
The easiest way is the typed shortcuts β the size is baked into the method name, so thereβs nothing to remember:
from PyMemoryEditor import OpenProcess
with OpenProcess(name="notepad.exe") as process:
address = 0x0005000C
value = process.read_int(address) # read a 4-byte int
print("Current:", value)
process.write_int(address, value + 7) # write it back
Thereβs a read_* / write_* pair for every common type:
name = process.read_string(address, 32) # reads a 32-byte field, returned up to the first NUL
For the generic API, see Reading and writing memory.
3. Run your first scanο
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:
from PyMemoryEditor import OpenProcess
target_value = 100
with OpenProcess(name="game.exe") as process:
for address in process.search_by_value(int, value=target_value):
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.
4. The Cheat Engine workflowο
The classic loop is:
Scan for a value you can see (e.g. your health is
100)Let the value change in the target (you take damage β
95).Refine: keep only the addresses that now hold the new value.
Read, write or freeze it.
with OpenProcess(name="game.exe") as process:
# 1. First scan β every address currently holding 100.
candidates = list(process.search_by_value(int, value=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, addresses=candidates)
if value == 95
]
# 4. Overwrite the survivors back to a high value.
for address in survivors:
process.write_int(address, 9999)
For big targets, see the refine-scan workflow to cache the region map once.
5. Pointer scanning β make an address survive restartsο
Addresses change every launch (ASLR). A pointer path starts from a fixed module offset and dereferences its way to your value β surviving restarts.
# 1. Scan β find pointer paths that resolve to the target address.
with OpenProcess(name="game.exe") as process:
# ... search for the address
paths = list(process.scan_pointer_paths(target_address, max_depth=3))
process.save_pointer_paths(paths, "health.json")
# ... restart the game, find the value's new address again ..
# 2. Rescan β keep only paths that still resolve to the new address.
with OpenProcess(name="game.exe") as process:
# ... search for the new address again
survivors = process.rescan_pointer_paths("health.json", new_target_address)
process.save_pointer_paths(survivors, "health.json")
# 3. Load β use the saved paths directly.
with OpenProcess(name="game.exe") as process:
paths = process.load_pointer_paths("health.json")
pointer = paths[0].rebase(process).to_pointer(process)
pointer.write(9999)
See the pointer scan guide for tuning options and the multi-run refine workflow.
Next stepsο
π 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.
βοΈ Responsible use
PyMemoryEditor talks to other processes through OS-level APIs. Only point it at processes you own or have explicit permission to inspect.