To lock Python code to a license key, do four things: validate the key against a server when the app starts, bind it to the machine hardware ID so it cannot be shared, verify the server signature so a fake server cannot bypass the check, and obfuscate the code so the check cannot simply be deleted. Skip any one of these and you leave an obvious hole. Here is how each layer works.
The four layers of locking Python code
Think of licensing as defense in depth. No single trick is enough, because each one has a bypass. Together they make cracking more expensive than paying — which is the only realistic goal.
1. Validate the key on startup
The first layer is the obvious one: when your program launches, send the key to your server and refuse to run if it comes back invalid.
from pylicensify import LicenseClient
client = LicenseClient(public_key="YOUR_PUBLIC_KEY")
result = client.validate("PY-XXXXXXXXXXXXXXXX")
if not result:
print("License is not valid:", result.error)
raise SystemExit(1)
On its own, this stops casual copying. It does not stop the three attacks below, which is why the other layers exist.
2. Bind the key to one machine (HWID)
A key that works on every machine is a key that gets shared once and used forever. Hardware binding fixes that. You derive a hardware ID from the machine and let the server tie the key to a limited number of devices.
import uuid
hwid = str(uuid.getnode()) # a stable per-machine value
The server records the HWID on first use. When the key shows up on a new machine and the device limit is reached, it is rejected. Set the limit to something reasonable — two or three devices for a desktop app — and let customers reset their own devices when they upgrade hardware, so you are not buried in support tickets.
3. Verify the signature
This is the layer most homemade licensing forgets, and it is the most important. A cracker does not need to break your key format. They point your app at a fake server that always answers "valid" and walk away. Ten minutes of work, protection gone.
The fix is to sign every response on the server with a private key that never leaves it, and verify that signature in the app with an embedded public key. A fake server cannot produce a valid signature, so it cannot fake a valid response. A good SDK does this check for you; if you build the client by hand, you must verify the signature yourself or the whole thing is theatre.
4. Obfuscate so the check cannot be removed
Signature verification stops a fake server. It does nothing about someone opening your program and deleting the four lines that call validate. Python makes this especially easy, because your source or bytecode is right there.
To raise the cost, ship your code obfuscated so the license logic is not sitting in plain sight next to a comment that says "license check here". Tools such as PyObfuscate transform the code so finding and patching the check is slow and frustrating. Obfuscation does not make cracking impossible; it makes it expensive, which is the point.
Do not forget offline users
Some of your best customers run on machines with no internet — labs, factories, secure environments. Do not lock them out. Issue a signed offline license file they can verify locally. Because the file carries its own signature, expiry, and device binding, it is as hard to forge as an online check, and you keep a customer you would otherwise lose.
from pylicensify import verify_offline_license
data = verify_offline_license("YOUR_PUBLIC_KEY", "license.lic")
Putting it together
A locked Python app validates on startup, binds each key to a device, verifies the server signature, and ships obfuscated — with an offline path for users who need it. Each layer covers a bypass in the others. You will not stop the one expert with unlimited time, but you will stop the shared key, the fake server, and the patched binary that make up the vast majority of real losses.
Want all four layers without building them yourself? Get started free — signed validation, device binding, and offline files are built in.
Frequently asked questions
How do I lock a Python script to one computer?
Bind the license key to a hardware ID (HWID) derived from the machine, such as uuid.getnode(). On each validation the server records the HWID and refuses the key on new machines once the device limit is reached, so the same key cannot run everywhere.
What is a HWID?
A HWID, or hardware ID, is a fingerprint that identifies one machine. It is often derived from the MAC address, disk serial, or CPU details. Licensing systems bind a key to one or more HWIDs so a single key cannot be shared with unlimited users.
Can users share my Python license key?
They can copy the string, but hardware binding stops it from working everywhere. When a key is tied to a device limit, extra machines are rejected. You can also detect sharing by watching for one key validating from many different IP addresses.
How do I stop someone removing the license check?
Signature verification stops a fake server, but not someone editing your code to skip the check. To raise that cost, obfuscate your Python so the validation logic is hard to find and patch. Obfuscation and signed validation work together.
Does licensing work if the user is offline?
Yes, if you issue a signed offline license file. The application verifies the file locally against an embedded public key, checking the signature, expiry, and device binding without any network connection.