JUk1-GH/gpt-promo-scanner: a Python toolchain for finding ChatGPT Business promo codes
ChatGPT Team(Business) 促销码自动扫描工具 — 批量发现/验证/价格收集,支持 17 国 34 个码,最高折扣 71% | ChatGPT Business promo code scanner — batch discovery, validation, price collection, 34 codes across 17 countries, up to 71% off
At a glance
- What is it?
- This project automates the discovery, validation and price collection of ChatGPT Business (formerly Team) promo codes across 17 countries using a Clash proxy and a browser access token. It is a batch workflow, not a one-command discount finder, and it depends on infrastructure the README does not help you set up.
- Who is it for?
- Adopt this if you already run Clash Verge with a multi-country node pool and you are comfortable managing a short-lived access token, because the discovery and validation scripts assume both. Do not adopt it if you want a single command that returns a working discount, or if your proxy setup cannot switch exit nodes programmatically.
- 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 124 days ago.
- What is it written in?
- Mainly Python, 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
What problem gpt-promo-scanner solves, and for whom
OpenAI issues promo codes to some channel partners, and the README states the standard ChatGPT Team (now Business) price is $50/month for two seats while those codes carry 40% to 71% discounts. The codes are not published anywhere central. They follow a loose naming convention, they are region-locked, and some have already expired. Finding a usable one by hand means guessing company names, switching proxy exits, and checking a Stripe page for each candidate.
This repository packages that guessing game into four Python scripts. discover_codes.py generates candidates, auto_scan.py validates them through a rotating Clash node pool, the metadata API call collects discount figures, and open_stripe.py turns a validated code into a checkout URL. The intended user is someone with a ChatGPT account, a Clash-compatible proxy client, and enough patience to run a batch scan and read a results file. It is not aimed at people who want a discount without touching a terminal.
The README is candid about the research process behind it. The author tried partner names from public OpenAI announcements, including SearchKings and Samsung SDS, and reports that none of them had codes. That negative result shapes the whole tool: the useful targets are small and mid-sized MSPs and regional AI tool companies, not the large firms that appear in press releases.
How the scan pipeline actually works
The mechanism is a three-stage loop over (candidate code, country) pairs. discover_codes.py builds candidate strings from a base name plus an ISO country suffix, lowercased and stripped of spaces, so thinkingmachines plus th becomes thinkingmachinesth. It then calls the eligibility API for each candidate. auto_scan.py takes over for bulk work: the README says it detects the Clash mode and proxy group, matches a node by region keyword, switches the node, measures latency, calls the checkout API, and records the outcome.
The output is three-way. A code comes back ELIGIBLE when the current account can pay for it directly, EXISTS when the code is real but the current exit region does not match, and not found when it does not exist or the token has expired. That third case is the trap. The README states plainly that an expired token makes every request return invalid_code, which the scan will report as a missing code. A whole run can look like a total failure when the only problem is authentication.
Results land in stripe_urls.txt and scan_results.json. open_stripe.py is deliberately decoupled: the README says it can be copied out and run alone with only curl_cffi installed, taking a promo code, an uppercase country code, and the access token as arguments. That separation is the sensible part of the design, because payment link generation does not need the scanning machinery or the proxy rotation logic.
Installing gpt-promo-scanner and running a first scan
The prerequisites are Clash Verge or another client exposing a Clash-compatible API, Python 3.9 or newer, and a ChatGPT account (the free tier is enough). The README notes the scripts default to the Unix socket at /tmp/verge/verge-mihomo.sock, and that a different path goes in config.toml.
Clone the repository and install the two dependencies listed in requirements.txt.
git clone https://github.com/JUk1-GH/gpt-promo-scanner.git
cd gpt-promo-scanner
pip install -r requirements.txtNext, obtain an access token. The README gives two routes: open https://chatgpt.com/api/auth/session in a browser and copy the accessToken field from the JSON, or run a fetch in the console. The token is a string beginning with eyJ.
const s = await (await fetch('/api/auth/session')).json();
console.log(s.accessToken);Copy the example config and paste the token into the openai section.
cp config.toml.example config.toml[openai]
token = "eyJhbGciOi..."Before committing to a long run, preview what a single region would scan. The README recommends testing one code first, because a batch of 1286 candidates was blocked by Cloudflare in the author's own account of the process.
python discover_codes.py GB --previewWhen the preview looks right, run the cross-matrix scan, which combines every known base name with every supported country. Add --auto-scan if you want price collection to follow automatically.
python discover_codes.py --crossA working run writes stripe_urls.txt and scan_results.json and prints counts for ELIGIBLE and EXISTS codes. To turn one into a payment link, switch to the matching country node first, then pass the code, the uppercase country code, and the token.
python3 open_stripe.py thinkingmachinesth TH eyJhbGciOi...The script prints a checkout.stripe.com URL. The README warns that the Clash node must already be on the matching country, so a TH code needs a Thai exit before the link is generated.
Where gpt-promo-scanner breaks or is the wrong tool
The hardest constraint is rate limiting. The README records that Cloudflare starts blocking after roughly 50 consecutive requests, and that a single 1286-candidate run was blocked outright. The scripts include interval control and automatic node switching, but the README's own advice is to slow down manually if that is not enough. There is no retry policy documented, and no queue that survives a restart.
Token expiry is the second failure mode, and it is worse because it is silent. Tokens last hours to days, and once one lapses every validation returns invalid_code, which the result table maps to not found. A user who does not know this will conclude that valid codes do not exist. The README suggests a cron job to refresh the token, but nothing in the repository does that for you.
The naming heuristic is a heuristic. The README lists explicit exceptions: some codes carry no country suffix at all, such as firstfocus, and UK suffixes are inconsistent, with talentgeniusuk valid while talentgeniusgb is not, and aibuildgroupgb valid while aibuildgroupuk is not. That means a clean scan can miss real codes. And codes expire permanently: geccogb and codestonegb were once usable and are not now.
Finally, the price figures are not what you pay. The README states the metadata API returns a per-seat discount value, so a two-seat plan saves value times two, and that Stripe computes discounts on pre-tax amounts while the public pricing page shows tax-inclusive prices. Germany's listed €26 per seat includes 19% VAT, so Stripe's base is €26 divided by 1.19. The README's own note is that the collected figure is not the final amount and the Stripe page is the accurate source.
How it differs from manual code hunting or generic web scrapers
The obvious alternative is doing this by hand: search for a promo code, switch your proxy to the matching country, open the checkout page, and see whether the discount applies. That approach needs no Python and no socket configuration, and for a single known code it is faster than setting up this repository. The difference is scale. Manual checking does not let you test nine base names against 34 country suffixes, and it does not produce a structured record of which combinations returned EXISTS versus not found.
A second alternative is a general-purpose scraping framework driving the same endpoints. That gives you retry logic, scheduling and proxy pools that this project does not have. What it does not give you is the domain knowledge encoded in the repository: the suffix convention, the UK exception, the list of known base names, the mapping from API response to ELIGIBLE, EXISTS and not found, and the Clash node-switching routine that ties an exit region to a country code. Those specifics are the actual content here, and they are the part a generic scraper leaves to you.
The trade-off runs the other way too. A general framework would let you resume an interrupted scan and back off intelligently on Cloudflare blocks. This project's scripts are linear, and the README's mitigation for blocking is human pacing.
Maintenance, licensing and what the repository expects of you
The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive arrangement, but it says nothing about the terms of the ChatGPT or Stripe services the scripts call, and it does not grant any right to use promo codes you find. Whether a code is valid for your account and region is a question for OpenAI's checkout flow, not for this licence. Nothing here is legal advice.
The last push to the default branch was on 2026-05-15, which is more than six months before today. The repository is not archived, but there are no releases, so there is no version history to pin against. The README itself documents that promo codes expire permanently and that partner programmes change, which means the embedded lists in known_codes.json and the base names in the discovery script will drift out of date without anyone updating them. You are adopting a snapshot of one person's research, not a maintained service.
Upgrade cost is low in one sense: requirements.txt pins only curl_cffi and tomli, and the latter is conditional on Python earlier than 3.11. There is no framework to migrate. The real cost is re-verifying the assumptions each time you run it, since a scanned code list from three months ago may be entirely dead.
Editorial conclusion
Adopt this if you already run Clash Verge with a multi-country node pool and you are comfortable managing a short-lived access token, because the discovery and validation scripts assume both. Do not adopt it if you want a single command that returns a working discount, or if your proxy setup cannot switch exit nodes programmatically. Before running anything, verify that config.toml points at the correct mihomo socket path, that a fresh accessToken returns a non-invalid_code response on one code, and that your Clash mode is not global, since the README records that global mode routes ChatGPT traffic through the GLOBAL group and breaks node switching.
Frequently asked questions
Does gpt-promo-scanner need a paid ChatGPT account?
No. The README states a free ChatGPT account is sufficient, and the access token is obtained from chatgpt.com regardless of subscription status.
Why does gpt-promo-scanner report every code as not found?
The most likely cause is an expired access token. The README notes that tokens last from hours to days and that once one lapses, all validation requests return invalid_code, which the results table maps to not found.
What is the difference between ELIGIBLE and EXISTS in gpt-promo-scanner results?
ELIGIBLE means the code works and the current account can pay for it directly. EXISTS means the code is real but the current proxy exit region does not match, so you need to switch to a node in the corresponding country.
Can I run open_stripe.py without the rest of gpt-promo-scanner?
Yes. The README says open_stripe.py is fully standalone and can be copied elsewhere, requiring only curl_cffi. It takes the promo code, an uppercase country code, and the access token as arguments.
How many requests can gpt-promo-scanner make before Cloudflare blocks it?
The README records that Cloudflare begins intercepting after roughly 50 consecutive requests. The scripts include interval control and automatic node switching, but the README advises slowing the pace manually if blocks persist.
Is the price gpt-promo-scanner collects the amount I will actually pay?
No. The README states the collected value is the API's discount figure, that it is applied per seat, and that Stripe calculates discounts on pre-tax amounts while public pricing pages show tax-inclusive prices. The Stripe checkout page is the accurate source.
Community notes