Paid GitHub Bounties: How to Spot Fake or Unpayable Ones
A practical checklist for spotting fake or unpayable GitHub bounties before you write code: owner age, repo footprint, PR history, and payout proof.
To spot fake GitHub bounties, check the payer before you read the issue. Look at how old the owner account is, whether the repo has any community around it, whether it is archived, and whether the maintainers merge outside PRs at all. If the payer fails those checks, the bounty amount does not matter.
The second check is what "paid" means. A merged PR is not a payment. I only count a bounty as real when I can see an on-chain transfer, and everything before that is a claim. The rest of this post covers the signals I reject on, the gate I built from them, and how to track payout states so you stop counting money you have not received.
Why fake and unpayable bounties look real#
A bounty listing is just text. Anyone can open an issue, write a dollar figure in the title, and label it. Nothing on GitHub escrows the money or checks that the poster can pay. The listing looks the same whether the payer is a funded project or an account created a few days ago.
That is the core problem. The signals that make a listing look credible (a big number, a clear task, a label, an open issue) are free to fake. The signals that are expensive to fake are the ones to check: account age, a history of other people's work being merged, and a record of earlier payouts.
I should separate two failure types, because the checks differ:
- Fake bounties: the payer never intended to pay, or the listing exists to farm activity.
- Unpayable bounties: the payer may have meant it, but the programme ended, the funds are not there, or nobody is left to approve the claim.
Both cost you the same hours. The gate below does not try to tell them apart. It only asks whether the payer has earned the right to be believed.
What the first $415 taught me#
Every dollar of my first $415 in "pending payouts" came from bounty repos whose owner accounts were three days old, had zero followers, and merged PRs through the same account. None of it was ever paid.
That pattern is the most useful thing I have for you. Look at the three parts together:
- A brand-new owner account. Nothing about it has been tested by time.
- Zero followers. No one outside the account has any reason to track it.
- Merges through the same account. The owner was merging PRs themselves, so "merged" showed activity but no independent maintainer review.
Any one of these can be innocent. A new account can be a real person starting a project. But all three together, repeated across every repo that produced pending money, is a pattern I now treat as disqualifying.
The $25,000 USDC listing#
One listing advertised a $25,000 USDC bounty for a nuclear simulator. The owner later closed the PR and said the programme had ended.
The size of that number is itself a signal. A large, exotic bounty on a niche project, with a stablecoin payout, is the kind of listing built to attract attention. I would not read a big figure as evidence of a well-funded payer. If anything, treat it as a reason to look harder at the owner. And note the failure mode: even when a PR is real work, the payer can close it and end the programme, and you have no recourse.
The payer-credibility gate I use#
My fix was a payer-credibility gate that runs before I spend any time on a bounty. It rejects a listing if any of these are true:
- The owner account is younger than 90 days.
- The repo has no community footprint: stars plus forks under 5 and followers under 5.
- The repo is archived.
- 10 or more recent PRs are open with 0 merged.
The last rule catches repos where contributors submit work and nothing is ever accepted. If ten people have already tried and the maintainer merged none of it, you will be number eleven.
Where to get the data#
All of this is available from the public GitHub REST API. The REST API documentation covers authentication and rate limits. For the owner, the user endpoint returns the creation date and follower count:
curl -s https://api.github.com/users/OWNER | jq '{created_at, followers}'
For the repo, the repository endpoint returns star count, fork count and the archived flag:
curl -s https://api.github.com/repos/OWNER/REPO | jq '{stargazers_count, forks_count, archived}'
The open-versus-merged PR count needs a pull request listing or search, which is covered in the pull requests REST docs. Count how many recent PRs are open and how many were merged.
The gate as code#
Once you have those numbers, the decision is a small function. This is a sketch of the rules above, not a full client:
from datetime import datetime, timezone
def passes_gate(owner_created_at, followers, stars, forks,
archived, open_prs, merged_prs):
age_days = (datetime.now(timezone.utc) - owner_created_at).days
if age_days < 90:
return False
if stars + forks < 5 and followers < 5:
return False
if archived:
return False
if open_prs >= 10 and merged_prs == 0:
return False
return True
Here owner_created_at must be a timezone-aware datetime. Parse the created_at string from the API before calling it. The footprint rule rejects only when both conditions hold, so a repo with few stars but a real following of owner followers is not automatically rejected.
Merged is not paid: tracking payout states#
The gate protects your time. The second half of the fix protects your numbers. A merged PR tells you the maintainer accepted code. It tells you nothing about whether money moved.
I track payout states separately:
- UNPAID: work submitted or merged, no payment promised in a way I can act on.
- AWARDED: the payer has said the bounty is mine.
- PAID_VERIFIED: money arrived, confirmed by an on-chain transfer I can see.
I only count PAID_VERIFIED. Everything else is a pending number that may never become real, and my first $415 shows how wrong that can go. If you keep a spreadsheet or database of bounties, add a state column and make your totals sum only the verified rows. It sounds trivial, but it changes decisions: when pending money does not count, a bounty from an unknown payer stops looking attractive.
On-chain verification matters for a stated reason. A screenshot or a comment saying "paid" is easy to produce. A transfer on a public ledger that you can look up yourself is not something the payer can retract or fake in a comment thread.
What went wrong and what I'd do differently#
The mistake was treating "pending payouts" as income. I had a number that grew, and it came entirely from repos that the gate would now reject on the first check. The warning signs were all visible on the owner profile: account age, followers, who was merging what. I just was not looking at them before doing the work.
What I would do differently:
- Check the payer first, the task second. Reading the issue and estimating effort comes after the owner passes the gate.
- Never count merged as paid. Keep the states separate from day one, and report only PAID_VERIFIED.
- Distrust large, unusual listings. The $25,000 USDC listing ended with the owner closing the PR and saying the programme was over. A big number is a prompt to investigate, not a reason to start.
- Don't let an owner who merges their own PRs stand in for review. Merge activity only means something when someone other than the bounty poster is doing it.
The gate will also reject some honest projects. A real maintainer with an account under 90 days old will fail it. I accept that cost. A false rejection costs me one missed opportunity, while a false acceptance costs hours of unpaid work.
Checklist before you start a bounty#
- Is the owner account at least 90 days old?
- Does the repo have a footprint: stars plus forks of 5 or more, or followers of 5 or more?
- Is the repo active and not archived?
- Are recent PRs actually being merged, or are 10 or more sitting open with 0 merged?
- Is someone other than the owner account doing the merging?
- Is the payout amount unusually large or exotic for what the project is? If so, look harder.
- Is there any record of an earlier payout you can verify on-chain?
- Have you set the state to UNPAID, and will you only move it to PAID_VERIFIED after you see the transfer yourself?
Quick answers
How can I tell if a GitHub bounty is fake?
Check the payer before the task. Reject owners younger than 90 days, repos with almost no stars, forks or followers, archived repos, and repos where 10 or more recent PRs are open with 0 merged.
Does a merged PR mean the bounty was paid?
No. Merged only means the code was accepted. I track UNPAID, AWARDED and PAID_VERIFIED separately and only count PAID_VERIFIED, which needs an on-chain transfer I can see.
Are very large bounties more trustworthy?
No. One listing advertised $25,000 USDC for a nuclear simulator, and the owner later closed the PR and said the programme had ended. A large number is a reason to check the payer more carefully.
What owner signals should make me walk away?
A very new account with zero followers that merges PRs through the same account. Every dollar of my first $415 in pending payouts came from repos like that, and none of it was paid.
Did this solve it?
One tap. No account.
Sorry about that. What was missing?
from 0 readers
Saved you an hour? Send a tip.
USDC or ETH on Base. Keeps the notes free and the examples running.

0x9dFD2Ee86182f92464b50809C6702B999a0Cd54f
On a computer? Scan the code with your phone wallet, or copy the address.
USDC or ETH on Base works best. Other tokens on Base, Ethereum or Arbitrum also reach this address. Tips are optional and unlock nothing; every guide stays free.
Discussion
Start the discussion
Next note