Python script that automates the process of redeeming gift codes in the game Kingshot. It reads a list of Player IDs and Kingdom IDs from one or more .csv files and sends signed requests to the game's giftcode redemption API to redeem the specified gift code for each player.
It was built with the goal of providing an alternative to the Discord Bot that I'm also helping develop. Setting up the bot and hosting it can take some effort to do, while this script can be run with one simple command. It can also be seen as providing a kind of backup option when your Discord bot is down and redemption is failing. The bot is awesome though - check it out if you haven't already.
- Python 3.9+: Download and install Python from python.org. Ensure Python is added to your system's PATH during installation.
- Required libraries:
pip install requests colorama
coloramais optional - without it the script runs fine, just without colored console output.
-
Get the script:
- Clone the repository:
git clone https://github.com/justncodes/ks-giftcode.git cd ks-giftcode - Or download
redeem_codes.pydirectly from the repository.
- Clone the repository:
-
Prepare the CSV file(s): see Supplying the kingdom under Usage.
-
Run the script: see Usage.
python redeem_codes.py --code <gift_code> [--csv <path_or_pattern>] [--kingdom <id>] [--delay <seconds>]-
--code: Required. The gift code you want to redeem (e.g.,KSFB150K). -
--csv: Specifies the player ID source. Defaults to the current directory if not provided. Can be:- A path to a single
.csvfile (e.g.,player_ids.csvorC:\Users\You\Documents\ids.csv). - A path to a folder/directory containing
.csvfiles. Every file ending in.csvin that folder is processed. - The pattern
*.csv(quote it if your shell needs it) or.to process every.csvfile in the current directory.
A
--csvpath that doesn't exist stops the run. Omit--csventirely to use every*.csvin the current directory. - A path to a single
-
--kingdom(alias--kid): Kingdom ID used for any player whose CSV row does not carry its own. Required unless every row is afid,kidpair. -
--delay: Seconds to wait between players. Defaults to1. Raise it if you see rate limiting.
The API checks the player ID and their kingdom together, and rejects the pair with USER INFO ERROR (err_code 40020) before it looks at the code. The script reports that as "Wrong kingdom for this player ID". There are two ways to supply it, and they can be mixed.
One kingdom for everyone (--kingdom) - the normal case for a single alliance. The CSV holds one ID per line, or comma-separated IDs:
57845354
98765432
12345678python redeem_codes.py --code KSFB150K --csv alliance.csv --kingdom 245A kingdom per player (fid,kid in the CSV) - for a list that spans kingdoms, e.g. after members have transferred. Lines starting with # are ignored:
# fid,kid
57845354,245
98765432,245
12345678,318python redeem_codes.py --code KSFB150K --csv alliance.csvRows carrying only an ID fall back to --kingdom, so both forms can live in one file. Given this CSV, 57845354 is redeemed in kingdom 318 and the other two in kingdom 245:
57845354,318
98765432
12345678python redeem_codes.py --code KSFB150K --csv mixed.csv --kingdom 245A row of exactly two numbers is read as fid,kid when the second number is 6 digits or shorter (kingdoms are small, player IDs are not). Every other row is read as a plain list of player IDs. If any player ends up without a kingdom, the script stops before sending anything.
-
Redeem for a specific file:
python redeem_codes.py --code KSFB150K --csv player_ids.csv --kingdom 245
-
Redeem for all
.csvfiles in a folder:python redeem_codes.py --code KSFB150K --csv /path/to/your/folder --kingdom 245
-
Redeem for a CSV that already carries per-player kingdoms:
python redeem_codes.py --code KSFB150K --csv alliance_with_kingdoms.csv
-
Go slower to stay well clear of rate limits:
python redeem_codes.py --code KSFB150K --csv player_ids.csv --kingdom 245 --delay 3
- Flexible CSV import: Reads player IDs from
.csvfiles, one per line or comma-separated, with an optional per-player kingdom. - Command-line interface: Accepts the
.csvfile path (or a directory, or*.csv), the gift code, and the kingdom as arguments. - Rate limit handling:
TOO FREQUENT(err_code40019) is a per-player limit. The script parks that player in a retry queue for 60 seconds and carries on with everyone else, coming back to them up to 3 times. - Retry logic: Automatically retries when the server asks for one (
TIMEOUT RETRY) or returns a transient HTTP error (429/502/503/504). The run aborts if 10 players in a row can't reach the API at all. - Early exit on a dead code: Stops the whole run on
TIME ERROR(expired),CDK NOT FOUND(bad code) orUSED(claim limit), since none of those depend on the player. - Safe to interrupt: Ctrl+C prints the summary before exiting, and re-running reports anything already redeemed as such.
- Wrong-kingdom reporting: Every player rejected with
USER INFO ERRORis listed at the end with the kingdom that was rejected, so you know exactly what to fix in your CSV. - Browser header rotation: Randomizes browser, version and platform headers on every request to avoid bot detection.
- Verbose logging: Timestamped, colored console output (with
colorama), mirrored toredeemed_codes.txt. - Summary report: Successes, already-redeemed, wrong-kingdom, other errors, rate limit events and total requests.
(Colorama adds colors in the actual terminal)
2026-03-04 10:30:00 - === Starting redemption script at 2026-03-04 10:30:00 ===
2026-03-04 10:30:00 - Gift Code: KSFB150K
2026-03-04 10:30:00 - Default Kingdom: 245
2026-03-04 10:30:00 - Using specified CSV file: player_ids.csv
2026-03-04 10:30:00 - Found 1 CSV file(s): player_ids.csv
2026-03-04 10:30:00 - Read 5 player IDs from player_ids.csv (encoding: utf-8-sig, 1 with a kingdom)
2026-03-04 10:30:00 - 4 player ID(s) had no kingdom in the CSV; using --kingdom 245.
2026-03-04 10:30:00 - Total unique player IDs to process: 5
2026-03-04 10:30:00 -
--- Starting processing cycle. Ready player IDs: 5 ---
2026-03-04 10:30:00 - Processing K245-12345678 [1/5] for code: KSFB150K
2026-03-04 10:30:01 - 12345678 - Result: Successfully redeemed
2026-03-04 10:30:02 - Processing K245-44445555 [2/5] for code: KSFB150K
2026-03-04 10:30:03 - 44445555 - Result: Already redeemed
2026-03-04 10:30:04 - Processing K245-57845354 [3/5] for code: KSFB150K
2026-03-04 10:30:05 - 57845354 - Result: Wrong kingdom for this player ID
...
2026-03-04 10:30:10 - --- Cycle finished. Total processed: 5/5 ---
2026-03-04 10:30:10 -
All 5 player IDs processed.
2026-03-04 10:30:10 -
========================= Redemption Summary =========================
2026-03-04 10:30:10 - Code Redeemed: KSFB150K
2026-03-04 10:30:10 - Total Unique Player IDs Found: 5
2026-03-04 10:30:10 - Total Player IDs Processed: 5
2026-03-04 10:30:10 -
--- Redemption Results ---
2026-03-04 10:30:10 - Successfully redeemed: 3
2026-03-04 10:30:10 - Already redeemed: 1
2026-03-04 10:30:10 - Wrong kingdom: 1
2026-03-04 10:30:10 - Other Errors/Failures: 0
2026-03-04 10:30:10 - Rate Limit Events: 0
2026-03-04 10:30:10 - Total API Requests: 5
2026-03-04 10:30:10 -
--- Wrong Kingdom (fix the kingdom in your CSV) ---
2026-03-04 10:30:10 - 57845354: kingdom 245 was rejected
2026-03-04 10:30:10 -
Total execution time: 0:00:10
======================================================================
All console output (without color codes) is appended to redeemed_codes.txt in the script folder.
pipcommand not found: Ensure Python is installed correctly and itsScriptsdirectory (Windows) or equivalent (macOS/Linux) is in your system's PATH environment variable.- ModuleNotFoundError: Run
pip install requests coloramain the environment you're actually using. - "have no kingdom and --kingdom was not given": The API needs a kingdom for every player. Pass
--kingdom <id>, or write the CSV asfid,kid. - "Wrong kingdom for this player ID" for everyone: The kingdom you passed is wrong for that list. Check the kingdom number in-game.
- "Wrong kingdom for this player ID" for a few players: Those members have transferred to another kingdom. Give them their own
fid,kidrows. - CSV File Not Found: Verify the path provided with
--csvis correct. Check for typos. If using*.csvor a folder path, ensure.csvfiles actually exist there. - Permission Denied (Log File): Ensure the script has permission to write files in the directory it's running from.
- Code expired / claim limit reached / code not found: The script stops the run - the code is dead or mistyped, so no player in the list can receive it.
- Lots of "Rate limited": The limit is per player ID, not per IP, so this usually means retries piling up on the same members. Raising
--delaygives the queue more room.
- The game's API requires the player's kingdom (
kid) on every redemption. Added--kingdomand support forfid,kidrows in the CSV. - Removed the login step (
/api/playerno longer exists). Player nicknames are unavailable, so output identifies players by kingdom and ID. TOO FREQUENT(40019) is handled as the per-player limit it is: the player is parked for 60s while the rest of the list continues, with a retry queue so nobody is silently skipped.- Runs stop early on
CDK NOT FOUNDas well asTIME ERRORandUSED. - Wrong-kingdom rejections (40020) are collected and listed separately in the summary.
- A
--csvpath that doesn't exist stops the run instead of falling back to every other.csvin the folder. - Ctrl+C stops cleanly and still prints the summary of what was redeemed.
- The run aborts if 10 players in a row can't reach the API.
- Requests are form-encoded with rotating browser headers, matching what the game's own web client sends.
- Added colored console output (requires
colorama), a--delayargument, and a fuller summary report.
- Fully functional - it's really just a 'reskin' of wos-giftcode
- Author: justncodes ([SIR] Yolo on #340)
- Repository: ks-giftcode
If you encounter any issues or have questions, feel free to open an issue on the GitHub repository.
This project is licensed under the GPLv3 License. See the LICENSE file for details.