Karuta Discord Script is a headless Python script for Windows that mimics realistic user behaviour to automatically drop and grab cards in Karuta, a Discord bot game.
⚠️ Be VERY CAREFUL when trading between accounts. Karuta is EXTREMELY strict with alting and has quite a strong anti-cheat to prevent alts.
⚠️ DO NOT run the drop script (main.py) for more than 10 consecutive hours or Karuta may flag your accounts for suspicious activity. Set self.TIME_LIMIT_HOURS_MIN and self.TIME_LIMIT_HOURS_MAX in config.py to control the time limit.
⚠️ DO NOT run the account login script (token_extractor.py) too many times in a row because you will get login rate-limited by Discord Web. The cooldown after being rate-limited is typically a few hours.
Discord's Terms of Service explicitly prohibits self-bots (as of August 2025, and for the foreseeable future). Unauthorized use of this script could result in account bans. Use at your own risk.
- In my experience, no accounts using this script have been banned by Discord, but I still recommend using throwaway accounts just to be safe.
- Clone the repository.
- Install Python 3.13.
- Initialize a virtual environment, then install the required dependencies by running:
pip install -r requirements.txt-
Ensure the Karuta drop mode (
kdropmode) is set to reactions, NOT buttons, in ALL the drop channels. -
All accounts must ONLY drop 3 cards, not 4. If an accounts drops 4 cards, the fourth card will not be auto-grabbed.
-
Create/buy accounts for the script to use! I highly recommend purchasing FULLY VERIFIED alt accounts from a trusted shop. A fully verified account means that it has a verified email AND phone number- a phone number connected to the account is imperative because Discord frequently phone-locks suspicious accounts. (You don't need to have access to the phone, it just needs to be connected to your account.)
- If you decide to buy accounts, I recommend purchasing from https://shop.xyliase.com/product/discord-accounts-%7C-fully-verified-tokens (I am not affiliated with this shop). As of July 2025, there is plenty of cheap stock and customer service is excellent.
-
Edit the
__init__constants inconfig.py.self.DROP_CHANNEL_IDSis a list of channels where the script will drop cards.- You MUST have at least 1 drop channel for every 3 accounts used.
self.SERVER_ACTIVITY_DROP_CHANNEL_IDSis used for two purposes:- During a Karuta special event, the special event account(s) will track these channels and automatically react to the special event emoji, if found.
- If CardCompanion is in use, the server drop account will also track these channels and automatically grab pog cards, if the setting is enabled.
- Read more about how these two features work in Usage Tips/Features below.
-
Enter your accounts into the script. You can accomplish this via two ways:
- Enter your emails and passwords in
self.ACCOUNTSintoken_extractor.pyusing the following format, and then runtoken_extractor.py.[{"email": "example_email@gmail.com", "password": "example_password"}, ... ] - OR, you can enter your tokens as a list of strings in
tokens.json. Leave the list intokens.jsonempty if you would like to use the token extractor for account logins instead.
- I recommend using tokens instead of account credentials so you can save time and avoid potential rate limiting. If you don't have your tokens on hand, you can automatically extract and save your tokens to
tokens.jsonby filling in your account credentials intoken_extractor.py, settingself.SAVE_TOKENS = True, then runningtoken_extractor.py.
- Enter your emails and passwords in
-
Run
main.py.
Tip
For the script to auto-grab all dropped cards, the number of accounts you input must be a multiple of 3 (3 accounts will work together in each drop channel). Make sure no accounts have 2FA enabled, and all accounts should have message access in all of self.COMMAND_CHANNEL_IDS and self.DROP_CHANNEL_IDS in config.py.
- Command Checker
- This script has a built-in command system that allows users to send messages, reactions, and button presses from any of the accounts in
tokens.json. - To set this feature up, edit the following constants in
config.py:self.COMMAND_USER_IDSrestricts message commands to these accounts- leave this list empty if you want to allow any user to send commands.self.COMMAND_CHANNEL_IDSare the channels where you are allowed to send message commands- leave this list empty if you want to disable commands entirely.
- To send a command from any account, manually send a message from a
self.COMMAND_USER_IDSaccount in anyself.COMMAND_CHANNEL_IDSchannel using the following format (without angle brackets):cmd <account_number |OR| account_number_range |OR| 'all'> <message>
- Ex 1.
cmd all kcollection o:wishlistsendskcollection o:wishlistfrom ALL accounts. - Ex 2.
cmd 1 kgive @ExxML <card_code>sends a card transfer from Account #1 (the first account listed inself.ACCOUNTS). A few seconds after the transfer is sent, the script will automatically confirm the transfer (from Account #1). - Ex 3. Suppose
cmd 3 kmultitrade @ExxML. After the trade items have been entered, typecmd 3 /lockto lock and confirm the trade (from Account #3). - Ex 4. Suppose
cmd 1 kmultiburn <filters>. When you are FULLY READY to complete the multiburn, typecmd 1 /multiburnto confirm the multiburn. - Ex 5.
cmd 1 /b <emoji / label>clicks the button on the most recent bot message (in self.INTERACTION_BOT_IDS) with the specified emoji OR label. For example,cmd 1 /b ✅orcmd 1 /b I understand. - Ex 6.
cmd 1 /r <emoji>reacts to the most recent bot message (in self.INTERACTION_BOT_IDS) with the specified emoji. For example,cmd 1 /r 💰. - Ex 7.
cmd /pause/cmd /resumepauses and resumes the script. - Ex 8.
cmd 1-10 kinventorysendskinventoryfrom Accounts #1-10.
- Ex 1.
- This script has a built-in command system that allows users to send messages, reactions, and button presses from any of the accounts in
Note
- ONLY single account arguments work with
give,/lock(for kmt),/multiburn(for kmb),/b, and/rcommands. Account number ranges andallwill not work with those commands. - If you mistype the account number for the
/lockor/multiburncommand, you must restart the trade/burn process. Sorry! - Automatic confirmation for the
kburncommand will not be supported. Use the/b 🔥command to manually confirm the burn, or usekmultiburninstead.
-
Special Event Grabber
- If there is a special event going on in Karuta, you can set up an account to automatically react to the event emoji(s) in all the drop channels and server activity drop channels. This feature supports multiple event emojis!
- To set this feature up:
- Set
self.SPECIAL_EVENT = Trueinconfig.py. - Enter string key and string value pairs in
special_event_tokens.jsonto automatically react to drops with the desired emoji, on the desired account.- For example, if I want "exampleSpecialToken2" to only grab 🌼 and "exampleSpecialToken1" to grab everything else, I would do:
{ "any": "specialEventToken1", "🌼": "specialEventToken2" }- Note: "any" is the only valid special key; all other keys must be emojis.
- Keep in mind that there cannot be duplicate keys in a dictionary; you can only have one token associated with each emoji.
- All special event tokens must, of course, have access to all
self.DROP_CHANNEL_IDSandself.SERVER_ACTIVITY_DROP_CHANNEL_IDS.
- For example, if I want "exampleSpecialToken2" to only grab 🌼 and "exampleSpecialToken1" to grab everything else, I would do:
- Enter the list of channels you want to track in
self.SERVER_ACTIVITY_DROP_CHANNEL_IDS. All drops in these channels will be tracked, regardless of whether they were generated by a user or from server activity. - Run
main.py.
- Set
- When there is no special event, you should set
self.SPECIAL_EVENT = Falseto avoid accidentally reacting to drops.
-
Server Drop Grabber
- You can set up accounts to watch server activity drop channels and automatically grab pog cards, as defined by CardCompanion. Note that you must have CardCompanion pog filters set up in order to use this feature.
- To set this feature up:
- Set
self.GRAB_SERVER_POG_CARDS = Trueinconfig.py. - Enter a string in
server_token.jsonwith the token that you want to grab all the server pog cards on - Enter the list of channels you want to track in
self.SERVER_ACTIVITY_DROP_CHANNEL_IDS. ONLY server activity generated drops in these channels will be tracked. - Run
main.py.
- Set
-
This script can be used in conjunction with CardCompanion, a Discord bot that can analyze and notify you of rare cards being dropped. If a "pog card" is dropped (a card that matches a certain stat (ex. >1000 wl)), CardCompanion will include an emoji in the message (see red circle below), indicating which card is the "pog card". The script will then ensure the grabber of the card is the same as the dropper, boosting the card stats and avoiding suspicion. If CardCompanion is not being used OR a "pog card" was not dropped, the grabber will be randomized by default.
- If you have CardCompanion set up, you can use the following settings in
config.py:- If you want to ONLY grab pog cards (perhaps to make your accounts' stats look less suspicious), set
self.ONLY_GRAB_POG_CARDStoTrue.- NOTE: While this setting is on, the script will prioritize using the dropper to grab the pog cards.
- If
self.ONLY_GRAB_POG_CARDS = Falsebut you want to occasionally skip grabbing a non-pog card, set a value forself.SKIP_GRAB_NON_POG_CARD_RATE. For every non-pog card dropped, there is aself.SKIP_GRAB_NON_POG_CARD_RATE% chance that the card will not be grabbed. Set to 0.0 if you wish to disable this feature and grab all non-pog cards.- In general, you should keep this enabled (set to some value) so that not all cards in a drop are grabbed, otherwise it'll look suspicious.
- If you want an account to automatically grab a pog card if it appears in a server drop channel, set up the Server Drop Grabber (
self.GRAB_SERVER_POG_CARDS) in Usage Tips/Features above. - If there are pog cards in the drop, you can make the dropper attempt to grab all the pog cards in the drop (boosting card stats) by setting
self.ATTEMPT_EXTRA_POG_GRABS = True, using extra grabs in the process.- If you want the dropper to automatically buy extra grabs after using them, set
self.ATTEMPT_BUY_EXTRA_GRABS = True. Note that this setting will do nothing ifself.ATTEMPT_EXTRA_POG_GRABS = False!- All accounts should have tickets on them in order to successfully buy the extra grabs; I recommend using the Auto-Runner Tool (see below) to automatically vote and get tickets.
- NOTE: If there are multiple pog cards, after the dropper attempts to grab all the pog cards, the other accounts in the channel will attempt to grab the rest of the pog cards after the first one, if any. This way, pog cards will always be grabbed, even if the dropper did not have enough extra grabs.
- If you want the dropper to automatically buy extra grabs after using them, set
- If you want all non-pog cards to be automatically burned after being grabbed, set
self.BURN_NON_POG_CARDS = True. Note that this setting will do nothing ifself.ONLY_GRAB_POG_CARDS = True. - If you want one or two of the other accounts in the channel (randomly chosen) to fight for a pog card alongside the dropper, set
self.FIGHT_FOR_POG_CARD = True. This behavior applies ONLY when exactly one pog card is dropped. If more than one pog card is dropped, this setting is ignored.- NOTE: When fighting for a pog card, the other two (non-pog) cards in the drop will not be grabbed.
- NOTE: If
self.ONLY_GRAB_POG_CARDS = Falseandself.FIGHT_FOR_POG_CARD = True, the fighting will take precedence over grabbing non-pog cards.
- If you want to ONLY grab pog cards (perhaps to make your accounts' stats look less suspicious), set
- If you have CardCompanion set up, you can use the following settings in
-
The
/bcommand can also be used on any bot buttons, not just Karuta. The list of allowed bots is set inself.INTERACTION_BOT_IDSincommand_checker.py, which includes OwO by default.
A separate script from the drop script above that automatically votes/works on all the accounts.
- Follow the Setup steps above to obtain a list of tokens in
tokens.json, or manually paste your tokens in a list. - Follow the Setup steps below for the Auto-Voter and Auto-Worker.
- Run
auto_runner.py.
- If you wish, edit
self.RAND_DELAY_MINandself.RAND_DELAY_MAXto change the (randomized) time between votes/works. - You may also edit
self.SHUFFLE_ACCOUNTSdepending on whether you want to randomize the order of accounts for voting/working. Generally, I would recommend keeping this settingTrue.
- Ensure your Chrome browser is up-to-date.
- DO NOT use a VPN while running this script. Cloudflare (the service Top.gg uses) flags VPNs.
- Set up work permits and job boards on all the acccounts.
- Ensure you have listed at least one drop channel in
config.py. A channel inself.DROP_CHANNEL_IDSwill be randomly selected to work in for every account.

