epicgames-freegames-node: scheduled Epic free game claims with a manual checkout step
Automatically login and find available free games the Epic Games Store. Sends you a prepopulated checkout link so you can complete the checkout after logging in. Supports multiple accounts, login sessions, and scheduled runs.
At a glance
- What is it?
- This self-hosted TypeScript service logs into Epic Games Store accounts on a cron schedule, finds the current free promotions, and sends a prepopulated checkout link through one of ten notifier types. It does not complete the purchase, and the README is explicit that device code sessions expire after 10 minutes, which is why the project ships a web server.
- Who is it for?
- Adopt it if you already run Docker with a persistent volume, you are comfortable putting Epic account credentials into a config file on that host, and you accept that a human still has to finish each checkout. Do not adopt it if you want unattended claims, if you cannot expose or tunnel port 3000 for captcha solving, or if you are unwilling to maintain an image that has had no tagged release since v5.1.0 in March 2024.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem is not finding free games, it is remembering to claim them
Epic gives away games on a weekly rotation, and a claim only counts if you complete checkout inside the window. The failure mode is mundane: the promotion ends, the link you saved is dead, and the game is gone from your library. epicgames-freegames-node targets that gap. It runs on a cron schedule, logs into the accounts you list, looks for the free promotions currently on offer, and sends you a checkout link that already has the items attached. You click, log in, and finish. The project is aimed at people who already self-host something, since the documented deployment path is a Docker image with a mounted config volume, and the topics list on the repository includes docker, self-hosted and reverse-engineering. It is not a desktop app and there is no mobile client. If you only have one Epic account and you check the store on Thursdays anyway, this is more machinery than the problem deserves.
Cron, notifiers, and a web server that only exists during a run
The architecture is a scheduled process plus a fan-out to messaging backends. A cron expression in the config controls when the run happens; the README's example is "0 0,6,12,18 * * *", four runs a day, and runOnStartup triggers one immediately when the container comes up. Each run iterates the accounts array, and when user interaction is needed the process starts an Express-style web server on port 3000 so you can solve a captcha or complete a login in a browser rather than chasing a new link every ten minutes. That ten minute figure is the whole reason the web server exists: Epic's device code session expires after 10 minutes, and the README says the redirect approach prevents the tool from sending a fresh link on that interval. One consequence deserves emphasis. The README states that to optimize for standby memory usage, the web server does not run when the process is not running, and is only available during a scheduled run. So the portal is not a dashboard you can open at any time. It appears when there is something to do and disappears afterwards. Notification delivery is a list of typed objects under notifiers, and you can configure as many of any type as you need. Documented types include email over SMTP, Discord webhooks with optional mentionedUsers and mentionedRoles, Telegram with an optional custom apiUrl and topic, Apprise, Pushover, Gotify, Home Assistant, Bark, ntfy and a generic webhook with custom headers.
Config lives in a mounted volume and accepts JSON5
Configuration is a combination of JSON and environment variables, and for each property the JSON value wins over the environment variable. The file lives in the mounted /usr/app/config volume and can be named config.json or config.json5, parsed as JSON5 so comments and trailing commas are legal. The README points to a generated config documentation site for per-option defaults and the environment variable key, which is where you look up the env tag for anything you would rather inject at runtime. A minimal shape looks like runOnStartup, cronSchedule, logLevel, webPortalConfig with baseUrl, an accounts array of email entries, and a notifiers array. If you keep everything in JSON, the README says the only remaining Docker configurables are the port and the volume, which makes the container definition short. The email notifier in the example carries smtpHost, smtpPort, emailSenderAddress, emailSenderName, emailRecipientAddress, secure and an auth object with user and pass. Every one of those is a real key you have to supply; there is no wizard and no discovery.
Two ways to reach the portal, and only one of them is under your control
The README gives two deployment shapes for the web server. If you know your way around a reverse proxy, you expose port 3000 (the example maps host port 81 to container port 3000 with -p 81:3000), set up whatever forwarding or DNS you need so the captcha page is reachable from wherever you are, and set webPortalConfig.baseUrl to that public address. If you cannot port forward, you set webPortalConfig.localtunnel to true and the project opens a tunnel for you. That second option is convenient and also the part I would think hardest about. A localtunnel URL is a public address for a page that exists to complete an Epic login, and it is created by a third party service rather than by your own infrastructure. The README does not describe authentication on the portal itself. If you go the localtunnel route, understand that you are trading control of the endpoint for the absence of a reverse proxy. Images are published to both ghcr.io/claabs/epicgames-freegames-node and charlocharlie/epicgames-freegames, with latest and debian tags on each. The debian variant exists for a specific reason: the README points to a known issue where Chromium hangs on login or notification, and suggests the Debian image as the workaround. That is a real constraint to know before you spend an evening debugging a container that never finishes a run.
The checkout is manual by design, and that is the limitation that matters
This tool does not buy anything. It sends a prepopulated checkout link, and you complete the checkout after logging in. Every claim therefore depends on a human acting inside the promotional window. If you sleep through the notification, or your Discord webhook is misconfigured, the run accomplishes nothing durable. There is a second, sharper failure mode: the whole flow can stall on a captcha or a login challenge, and the portal that would let you resolve it is only alive during that run. Miss the window and the run ends with the account untouched. The project also asks for Epic credentials in a config file on a host you control, which is an operational risk you are accepting rather than a flaw in the code. And there is an availability signal worth weighing: the most recent tagged release is v5.1.0 from March 2024, with v5.0.0 in June 2023 and v4.1.0 in May 2022 before that. The repository is not archived and the last push is recent, but the release cadence is slow, and because this project talks to an undocumented store API, slow releases mean you are the one who discovers when something upstream changes. If you need guaranteed unattended claims, this is the wrong tool, and no configuration option in the README changes that.
Compared with just claiming games by hand in a browser
The obvious alternative is the Epic Games Store itself. You open the store page, add the free items, and check out while logged in, with no third party holding your credentials and no container to patch. The difference in approach is who holds the schedule and the session. Manual claiming puts both in your browser and your memory; epicgames-freegames-node puts the schedule in a cron expression and the session in a config volume, and pays for that with a checkout link you still have to click. There is no partial credit here: the automation covers discovery and cart preparation, and stops exactly where the human is required. A second alternative is a notification-only setup, where you subscribe to a feed of current Epic free promotions and claim them yourself. That avoids storing credentials entirely and avoids the web portal, at the cost of losing the prepopulated cart, which is the specific thing this project builds. Choose between them on whether the cart preparation is worth the credential handling. For most people with a single account, it is not. For someone running several accounts, the accounts array and the multi-notifier fan-out are the features that justify the setup.
Licence, maintenance, and what a version bump costs you
The project is MIT licensed, which permits commercial and private use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive licence and it does not obligate you to publish changes. It also means the maintainers offer no warranty, and nothing about the licence creates a support relationship. Treat the following as engineering observations rather than legal advice, and read the LICENSE file yourself if the distinction matters to you. On maintenance: the upgrade path is a container pull plus a config review, because new options appear in the config documentation site and the JSON file is the source of truth over environment variables. Because the config file accepts JSON5 with comments, you can annotate your own file as you go, which helps when you come back in six months. The real cost is not the pull, it is the dependency on Epic's authentication and store endpoints. When those change, the symptom will be a run that hangs or a login that never completes, and the README's own advice about the Debian image exists precisely because Chromium behaviour inside the container has already caused that class of problem. Budget for reading the issue tracker when a run stops notifying, not for a predictable release train.
Editorial conclusion
Adopt it if you already run Docker with a persistent volume, you are comfortable putting Epic account credentials into a config file on that host, and you accept that a human still has to finish each checkout. Do not adopt it if you want unattended claims, if you cannot expose or tunnel port 3000 for captcha solving, or if you are unwilling to maintain an image that has had no tagged release since v5.1.0 in March 2024. Before deploying, verify two things: that your chosen notifier actually delivers by setting testNotifiers to true in config.json, and that the web portal answers on webPortalConfig.baseUrl during a run, because the README states the web server only runs while the process is running.
Community notes