Python 3 and a terminal. No money is involved and no platform is contacted.
macOS and Linux include Python; on Windows install it from python.org with
“Add python.exe to PATH” ticked, then check with
python3 --version.
You need no financial knowledge whatever. The arithmetic below is addition and percentages, and every term is explained where it appears. The company names are invented. Run the five files in order — each writes a small file the next one reads, which is how the totals in step 4 stay honest instead of being retyped.
The Largest Category of Loss
Of all the fraud reported to the FBI's Internet Crime Complaint Center for 2025, investment fraud produced the largest losses of any category -- more than $8.6 billion (FBI IC3 2025 Internet Crime Report, accessed 5 September 2026). It is not the most common complaint by count; phishing is. It is the one that takes everything, because the victim is not tricked into a single mistaken payment. They are recruited into a relationship and then invest deliberately, repeatedly, over months.
The dominant form is often called pig butchering, a translation of the Chinese term sha zhu pan: the victim is "fattened" with attention and apparent profits before being taken. Romance and investment fraud have merged into one operation, because affection is simply the most efficient way to establish the trust the investment stage requires.
Many of these operations run from large compounds staffed by trafficked workers following written scripts, with quality control and performance targets. The person you are speaking to may be reading from a manual, may not be using their own photographs, and in some cases is themselves a victim. Nothing about the warmth you experience is improvised.
The Playbook, Stage by Stage
The script is remarkably consistent. Knowing the sequence is what lets you recognise stage two while you are still standing in it.
A stray text, a misdirected WhatsApp message, a friendly comment, or a dating-app match. The opener is deliberately innocuous. When you reply politely, they apologise charmingly and a conversation begins.
Weeks or months of real conversation with no mention of money. They remember details, they check in about your day, they are available when you are lonely. This stage is the product. Anyone can be drawn into it, and being intelligent offers no protection.
They mention trading in passing -- an uncle with inside knowledge, a strategy their firm uses. They do not offer to include you. They wait for you to ask, which makes the idea feel like yours. If you show interest they may even hesitate, which removes your last suspicion.
You put in a modest amount through a polished app or website. It shows a profit. You withdraw successfully and the money arrives in your account. This is the pivotal moment: a successful withdrawal converts scepticism into confidence, and it is completely fabricated -- the platform is a display, and your "withdrawal" was paid from your own deposit.
Larger amounts, a limited-time opportunity, encouragement to remortgage, borrow, or move retirement savings. The dashboard shows extraordinary growth. Everything you see is a number in a database the operators control.
You try to withdraw a large sum and cannot. There is a tax, a compliance fee, an anti-money-laundering deposit, a fine for early exit. Each payment unlocks a new obstacle. This stage exists purely to extract whatever is left after the principal is gone.
Months later, someone contacts you claiming they can recover your funds -- a lawyer, a blockchain investigator, an "asset recovery agency". They are frequently the same operation returning to the same list. Legitimate recovery is never sold to you by cold contact.
The Signals
Any single item can have an innocent explanation. Two or three together should stop the conversation.
- The relationship started with a stranger contacting you -- a wrong-number text, an unexpected friend request, an unsolicited direct message
- They move you off the original platform quickly -- to WhatsApp, Telegram or Signal, where there is no moderation and no report button
- They will not do a spontaneous video call -- there is always a camera problem, bad reception, or a security policy at work. A pre-arranged call is weaker evidence now that real-time deepfakes exist
- Their life story explains their absence -- offshore engineer, military deployment, surgeon abroad. The script needs a reason you can never meet
- Investment through an app or site only they can introduce you to -- not a broker you can find independently and open an account with yourself
- Deposits in cryptocurrency, or transfers to an individual's account rather than a regulated institution
- Returns that are steady and impossible -- real markets lose money sometimes. A line that only goes up is a rendering, not a portfolio
- Withdrawals require a payment -- no legitimate platform ever asks you to send money in to take money out. Taxes and fees are deducted from the balance
- Pressure and secrecy -- urgency about a closing window, and advice not to discuss it with family or your bank because they "will not understand"
You must pay a fee to withdraw your own money. This one signal appears in nearly every case and has no legitimate counterpart anywhere in regulated finance. If you are asked for it, the money is already gone and every further payment is a pure loss.
Verifying Before You Invest
- Check the regulator's register directly -- go to the regulator's own website and search the firm. Never use a link, phone number, or reference number the firm gave you
- Check the warning lists -- most regulators publish lists of unauthorised firms and clone operations
- Beware of clone firms -- a common tactic is to copy the name and registration number of a genuinely regulated business. Verify the contact details on the register, not the ones you were sent
- Look up the domain's age -- a "ten-year-old trading house" on a domain registered four months ago is answered
- Reverse image search the profile photographs -- stolen photos are still common, though increasingly replaced by AI-generated faces that will not match anything
- Talk to one person outside the relationship before sending money -- a family member, your bank's fraud team, an independent adviser. The instruction to keep it private exists solely to prevent this
Helping Someone Who Is In One
This is genuinely difficult. The victim is in a relationship they value and is being told by someone they trust that their family will not understand. Direct contradiction usually pushes them closer to the scammer.
- Do not lead with "you are being scammed" -- it forces them to defend the relationship, and the script has already prepared them for exactly this conversation
- Ask questions instead of making assertions -- what happens if you try to withdraw everything today? Who regulates them? Why can they not do a video call now?
- Focus on the withdrawal fee -- it is concrete, checkable, and does not require them to accept that the person is fictional
- Keep the door open -- shame is what keeps victims silent and paying. Someone who fears being told they were foolish will hide the next payment
- Involve the bank early -- fraud teams handle this constantly and can intervene without it becoming a family argument
If It Has Already Happened
- Stop paying immediately -- including any fee promised to release funds. There is nothing to release
- Contact your bank and any exchange used -- crypto is rarely recoverable, but exchanges can sometimes freeze accounts if told quickly
- Report it formally --
ic3.govin the US, or your national fraud service. These reports are how compounds and wallet clusters get mapped - Preserve everything -- chat logs, profile names, wallet addresses, transaction hashes, screenshots of the fake platform. Do not delete the account in anger
- Expect the recovery scam -- treat every unsolicited offer of help as part of the same operation
- Tell someone you trust -- isolation is the mechanism that made the fraud work, and it is what keeps it working afterwards
Run the Platform's Books Yourself, in Five Steps
People who lose money to investment fraud are not, as a rule, greedy or careless. They are shown a dashboard with a number on it, they test whether the number is real by withdrawing a little, the money arrives, and they reasonably conclude the thing works. Everything after that follows logically from a correct experiment with a rigged answer. In the next twenty minutes you will keep the platform's real books alongside its displayed ones, watch the test withdrawal do its job, run the fee sequence that extracts more than the original deposits, and meet the second fraud that arrives afterwards. Every line of output below came from running these files.
Go: open a terminal in a folder you can write to — cd ~/Desktop on macOS or Linux, cd %USERPROFILE%\Desktop on Windows.
Do: save this as platform.py and run python3 platform.py.
"""The platform's books, kept honestly for once."""
import json
books = {"real_money_received": 0.0, "displayed_balance": 0.0, "trades_placed": 0}
def deposit(amount):
books["real_money_received"] += amount # this leaves your bank
books["displayed_balance"] += amount # this is a number in their database
print("deposited %8.2f dashboard now shows %8.2f" % (amount, books["displayed_balance"]))
def grow(percent):
"""No market is touched. A number is multiplied."""
books["displayed_balance"] *= (1 + percent / 100)
print(" %8s dashboard now shows %8.2f (+%.0f%%)"
% ("", books["displayed_balance"], percent))
deposit(250)
grow(18)
deposit(1000)
grow(22)
deposit(5000)
grow(31)
print()
print("real money that left your bank :", "%.2f" % books["real_money_received"])
print("trades actually placed :", books["trades_placed"])
print("dashboard balance :", "%.2f" % books["displayed_balance"])
print()
json.dump(books, open("books.json", "w"))
print("The first small deposit and its profit are what buy the large one.")
You should see: a healthy-looking account and a trade count of zero:
deposited 250.00 dashboard now shows 250.00
dashboard now shows 295.00 (+18%)
deposited 1000.00 dashboard now shows 1295.00
dashboard now shows 1579.90 (+22%)
deposited 5000.00 dashboard now shows 6579.90
dashboard now shows 8619.67 (+31%)
real money that left your bank : 6250.00
trades actually placed : 0
dashboard balance : 8619.67
The first small deposit and its profit are what buy the large one.
The grow function is the entire product. It multiplies a number. No
market is contacted, no asset is bought, and nothing is at risk except the money that already
left your bank — which is why the returns can be whatever the operator finds persuasive,
and why they are so consistently good. A real investment has bad months because it is
exposed to something real. A number in a database does not.
If not: PermissionError means the folder is not writable —
cd somewhere you own, because this script writes books.json for the
later steps to read.
Go: the same folder. This is the step that explains the whole thing.
Do: save this as trust.py and run python3 trust.py.
"""Why people send the big deposit: the small withdrawal that really arrives."""
deposited = 250.00
shown_profit = 45.00
test_withdrawal = 100.00
print("you deposit : %8.2f" % deposited)
print("dashboard shows : %8.2f" % (deposited + shown_profit))
print("you test it, asking for %6.2f" % test_withdrawal)
print("it arrives, next day : %8.2f <- real money, really paid" % test_withdrawal)
print()
print()
print("their net position : %8.2f ahead" % (deposited - test_withdrawal))
print("your conclusion : the platform pays out")
print()
print("This is the whole mechanism. The test withdrawal is not a mistake")
print("and not a loophole -- it is the marketing budget, and it works")
print("because it answers the exact question a careful person asks first.")
You should see: real money genuinely arriving, and the operator still ahead:
you deposit : 250.00
dashboard shows : 295.00
you test it, asking for 100.00
it arrives, next day : 100.00 <- real money, really paid
their net position : 150.00 ahead
your conclusion : the platform pays out
This is the whole mechanism. The test withdrawal is not a mistake
and not a loophole -- it is the marketing budget, and it works
because it answers the exact question a careful person asks first.
This is the part that makes victims feel foolish afterwards, and they should not. Testing a platform by withdrawing from it is exactly the right instinct — it is what a careful person does, and the fraud is built specifically to pass that test. Paying out 100 against a 250 deposit costs the operator 150 less than nothing, and it converts a cautious person into a confident one.
So the lesson is not “always test with a withdrawal”. It is that a successful small withdrawal carries almost no information, because it is cheap for a fraud to provide and expensive to refuse.
If not: the numbers here are fixed constants and do not depend on the previous step, so they
should match exactly. If their net position prints a negative number, the
subtraction was reversed.
Go: the same folder.
Do: save this as withdraw.py and run python3 withdraw.py. It reads
the balance written by step 1.
"""You ask for your money. This is the part that is designed most carefully."""
import json
books = json.load(open("books.json"))
balance = books["displayed_balance"]
paid_out = 0.0
extra_paid_in = 0.0
DEMANDS = [
("withdrawal processing fee, 8% of balance", 0.08),
("capital gains tax, prepaid, 15%", 0.15),
("anti-money-laundering verification bond", 0.10),
("international transfer insurance", 0.05),
]
print("dashboard balance: %.2f" % balance)
print()
for reason, rate in DEMANDS:
fee = balance * rate
extra_paid_in += fee
print(" they ask for %8.2f -- %s" % (fee, reason))
print(" you pay it. released so far: %.2f" % paid_out)
print()
print("extra real money sent AFTER asking to withdraw : %.2f" % extra_paid_in)
print("money actually received : %.2f" % paid_out)
print()
books["fees_extracted"] = extra_paid_in
books["test_paid_back"] = 100.00
json.dump(books, open("books.json", "w"))
print("Every demand is a percentage of a number they invented, which is why")
print("a bigger fake balance produces bigger real fees. The withdrawal is")
print("never refused -- refusal would end the relationship.")
You should see: four demands, and nothing released:
dashboard balance: 8619.67
they ask for 689.57 -- withdrawal processing fee, 8% of balance
you pay it. released so far: 0.00
they ask for 1292.95 -- capital gains tax, prepaid, 15%
you pay it. released so far: 0.00
they ask for 861.97 -- anti-money-laundering verification bond
you pay it. released so far: 0.00
they ask for 430.98 -- international transfer insurance
you pay it. released so far: 0.00
extra real money sent AFTER asking to withdraw : 3275.47
money actually received : 0.00
Every demand is a percentage of a number they invented, which is why
a bigger fake balance produces bigger real fees. The withdrawal is
never refused -- refusal would end the relationship.
Notice that no request is ever refused. Refusal would end the relationship and trigger a complaint; instead every reply is “yes, of course — once this is settled”. Each demand is calculated as a percentage of a number the operator chose, so the fake profits are not the prize, they are the pricing mechanism: a larger invented balance justifies larger real fees.
Every item on that list is also independently checkable and false. Tax authorities do not collect tax through the platform you traded on. There is no such thing as a refundable anti-money-laundering bond. Legitimate withdrawal charges are deducted from the amount sent, never demanded as a separate payment beforehand — and that single rule identifies this fraud on its own.
If not: FileNotFoundError: books.json means step 1 has not run in this folder.
If the percentages produce different figures, the balance in books.json is from an
earlier run — re-run step 1 to reset it.
Go: the same folder.
Do: save this as total.py and run python3 total.py.
"""Add it all up, once."""
import json
books = json.load(open("books.json"))
deposits = books["real_money_received"]
fees = books["fees_extracted"] # written by withdraw.py, not retyped
test_paid_back = books["test_paid_back"]
shown = books["displayed_balance"]
out_of_pocket = deposits + fees - test_paid_back
print("%-42s %10.2f" % ("real money you sent as deposits", deposits))
print("%-42s %10.2f" % ("real money you sent as 'fees'", fees))
print("%-42s %10.2f" % ("real money you received back", test_paid_back))
print("-" * 53)
print("%-42s %10.2f" % ("actual loss", out_of_pocket))
print()
print("%-42s %10.2f" % ("what the dashboard says you own", shown))
print("%-42s %10s" % ("what backs that number", "nothing"))
print()
print("The gap between the last two lines is the reason people keep paying:")
print("every fee looks small next to the balance it is supposedly unlocking.")
You should see: a loss larger than every deposit combined:
real money you sent as deposits 6250.00
real money you sent as 'fees' 3275.47
real money you received back 100.00
-----------------------------------------------------
actual loss 9425.47
what the dashboard says you own 8619.67
what backs that number nothing
The gap between the last two lines is the reason people keep paying:
every fee looks small next to the balance it is supposedly unlocking.
The fees alone came to more than half the deposits, and they were paid after the victim had already decided something was wrong enough to want their money out. That is not irrationality; it is the sunk-cost position the design creates deliberately. Each individual fee is small compared with the balance it appears to unlock, so each individual decision looks sensible.
The line that matters is the last one. Any platform can display any number. The question that separates an investment from a screenshot is where the asset is held, who else can confirm it exists, and which regulator you could complain to — and for this kind of operation all three answers are missing before you send anything.
If not: if fees prints 0.00, step 3 has not been run since step 1
— the figure is written into books.json by withdraw.py
deliberately, so that no number in this step is retyped from the previous one.
Go: the same folder.
Do: save this as recovery.py and run python3 recovery.py.
"""Weeks later, someone contacts you offering to get the money back."""
import json
books = json.load(open("books.json"))
lost = books["real_money_received"] + books["fees_extracted"] - books["test_paid_back"]
OFFERS = [
("'Blockchain Asset Recovery Ltd'", "upfront retainer", 0.10),
("'CyberFraud Investigations'", "court filing fee", 0.07),
("a 'police cyber unit' caller", "evidence handling fee", 0.05),
]
print("your documented loss: %.2f" % lost)
print()
extra = 0.0
for who, what, rate in OFFERS:
ask = lost * rate
extra += ask
print(" %-34s asks %8.2f for the %s" % (who, ask, what))
print()
print("second-wave losses if you accept all three: %.2f" % extra)
print()
print("They know the exact amount because the first group sold the list --")
print("names, amounts, dates. Being a victim once is what qualifies you.")
print()
print("Genuine facts: no police force charges a fee to investigate a crime.")
print("Regulated recovery firms are paid from what they recover, not in")
print("advance. And no private company can reverse a completed transfer.")
You should see: three approaches, each priced off the loss:
your documented loss: 9425.47
'Blockchain Asset Recovery Ltd' asks 942.55 for the upfront retainer
'CyberFraud Investigations' asks 659.78 for the court filing fee
a 'police cyber unit' caller asks 471.27 for the evidence handling fee
second-wave losses if you accept all three: 2073.60
They know the exact amount because the first group sold the list --
names, amounts, dates. Being a victim once is what qualifies you.
Genuine facts: no police force charges a fee to investigate a crime.
Regulated recovery firms are paid from what they recover, not in
advance. And no private company can reverse a completed transfer.
The detail people find hardest to believe is that the callers know the exact figure. There is no mystery to it: victim lists are a traded commodity, complete with amounts and dates, and having lost money once is the qualification that puts you on one. Being contacted by a “recovery” service is therefore evidence of nothing except that the first group has sold your details.
What to do instead, in order. Contact your bank immediately — not the platform — and ask them to attempt a recall; speed is the only factor that helps. Report it to your national fraud reporting body and to the police, both of which are free. Preserve everything: messages, screenshots, transaction references. And treat every unsolicited offer of recovery as the second half of the same crime.
If not: if the loss figure differs from the previous step, books.json was
regenerated in between — run steps 1 and 3 again in order. The three percentages are fixed,
so the individual asks scale directly with that total.
Without scrolling up: a friend shows you a trading account that has grown 40% in three months, and tells you they already withdrew 200 successfully last month, so it is definitely real. What have they actually proved, and what one question would you ask them? Answer: they have proved that the operator was willing to send 200, which step 2 showed costs a fraud less than nothing when set against the deposits it unlocks — a successful small withdrawal is the cheapest thing such a platform can provide and is built into the design. The growth figure proves less still, because step 1 showed the balance is a number multiplied by a function, with no trade behind it. The question to ask is not about the platform at all: which regulator authorises them, under what registration number, and does that number appear on the regulator's own public register when you look it up yourself — not on a link the platform supplied. If the answer is missing, evasive, or a certificate image, nothing else about the account is worth discussing.
Now do it without the page: change platform.py so grow occasionally applies a
negative percentage, then look at the resulting dashboard and ask yourself honestly
whether it looks more or less credible than the smooth version. Most people find the losing
months make it look more real — which is why the more careful frauds include them. Then do
the useful part: find your country's financial regulator's public register, and look up one firm
you already deal with, so you know how the check works before you ever need it in a hurry.
Summary
- Investment fraud is the biggest loss category -- more than $8.6 billion reported in 2025 alone
- The relationship is the attack -- weeks of genuine warmth precede any mention of money
- The small successful withdrawal is bait -- it is paid from your own deposit to establish credibility
- Paying a fee to withdraw is the defining signal -- it never happens in legitimate finance
- Verify on the regulator's own website, never through details the firm supplied
- Shame keeps the fraud alive -- these are professional operations, and being taken in says nothing about your intelligence
Never invest through a platform that was introduced to you by someone you met online. Not a smaller amount, not as a test. If an opportunity is real, it will still be there after you have found the firm independently on a regulator's register.