- A profile farm is one laptop running fifty antidetect profiles with a residential exit each; the machine is the part it cannot rotate.
- Photo verification binds a face to a profile, not a device to a count; the same face can verify profile after profile.
- Evaluate after the profile row exists and before it is shown, with accountId set, so linked_accounts arrives in the same response.
- Step up at two linked accounts, hold at three; block on the antidetect, automation and proxy signals, never on a VPN alone.
- Do not write a rule on tampering_score: on our bench it read 0.0029 on every profile while the tampering flag moved.
On this page
A fake dating profile costs its operator one browser profile, a slice of residential-proxy bandwidth and a mailbox that receives. It costs you the real user it matches with; the same kit produces marketplace listings that exist only until a deposit clears. Photo verification, email confirmation and IP rules stand in the way, and the farm passes them by design: a face at the phone, an address that gets the mail, a home IP behind every profile. What it cannot change is that its profiles share a machine. This playbook follows one farm from setup to payout, then puts a device-linking check between profile creation and the moment it is shown.
How a dating profile farm is run
- The machine. One laptop, one antidetect browser, one profile per account. Multilogin's Pro 50 plan is $19.17 a month billed annually ($29 monthly) for 50 profiles; GoLogin sells its Professional tier up to 100 (Multilogin pricing, GoLogin pricing, both checked 2026-08-29). Each profile is its own cookies, storage and fabricated device identity: fifty devices where there is one. Tool pages: Multilogin, GoLogin; the wider write-up is how antidetect browsers spoof the fingerprint.
- The network. A residential proxy pool billed by the gigabyte: Oxylabs lists its Starter tier at $6/GB and Decodo lists $4/GB pay as you go (Oxylabs, Decodo, both checked 2026-08-29). To the app the exit is home broadband:
network.residentialistruewhen neither the cloud-server nor the proxy check fired. The residential-proxy pillar covers which signals survive a rented home IP; this post is the device half. - The identity. A photo set, a bio, an age, and a mailbox that receives: a burner domain (the community-maintained disposable-email-domains blocklist held 8,368 domains on 2026-08-29) or a relay. Apple's Hide My Email issues random
@privaterelay.appleid.comaddresses that forward to the real inbox (Apple Support, checked 2026-08-29). - The signup. Done by hand for the profiles that will earn, scripted for the ones that will not; the scripted ones trip
device.automation. Where the app asks for a selfie, a real face is supplied. - The payout. Romance: the conversation moves to a messaging app and the money follows; the FBI's Internet Crime Complaint Center logged 17,910 Confidence/Romance complaints and $672,009,052 in reported losses for 2024 (IC3 2024 Internet Crime Report, checked 2026-08-29). Redirection: the profile pushes a link to a paid site or a wallet. Neither earns before the profile is shown and matched, which is why the check goes there.
The same farm, selling instead of dating
Swap the bio for a listing and nothing else changes. The FTC describes the rental version: a listing copied from a real one or invented at "surprisingly low rent", an owner who "will usually claim to be out of the country", and a deposit by wire, gift card or cryptocurrency (FTC, Rental Listing Scams, checked 2026-08-30). About half of those who reported a rental scam in the 12 months to June 2025 said it began with a fake Facebook ad (FTC press release, 22 December 2025, checked 2026-08-30). One deposit is the whole return, so the operator wants many listings live from many "sellers". Read the rest with listing published in place of profile shown.
Why photo verification and email confirmation miss it
Photo verification checks a face, not a count. Tinder's process: "A member takes 2 selfies mirroring the poses shown" (Tinder Safety Center, checked 2026-08-29). Bumble assigns one of "a hundred random photo poses" and has a person review the selfie (Bumble, checked 2026-08-29). Both ask whether the person in the photos holds the phone; neither asks how many verified profiles that face, or that device, now owns.
Email confirmation checks that a mailbox receives. A burner domain receives; a relay receives and belongs to a real Apple ID. Deduplicating on the address fails both ways: the farm has unlimited addresses, and a real user on a relay looks like the farm. We wrote up why burner-domain lists are an escalation signal, not a gate.
IP rules see a fresh home address on every profile. Per-IP limits and geo rules never fire against a pool priced by the gigabyte.
Phone verification proves a number received a text, and can bill you for the privilege; the SMS pumping playbook covers the invoice side.
None of these ask the two questions that matter: how many profiles came from this machine, and is it telling the truth about itself. Our multi-accounting pillar covers device linking as the general counter; here it is applied to the one action a dating app or a marketplace sells, being shown. The other fraud playbooks follow the same shape.
Run your own signup or checkout traffic through this: the free scanner returns the same verdict the API does.
Open the scannerThe tells
Every row is a field from the evaluate response. Device rows need fingerprintEventId; device.linked_accounts also needs your accountId — on a dating app, the profile id.
| Tell | Field / reason code | Weight |
|---|---|---|
| Several profiles from one device | device.linked_accounts, device.multi_account, reason multi_account_device | Step-up at 2, block at 3 or more |
| Fingerprint that contradicts its engine | device.antidetect, reason antidetect_browser | Block |
| Scripted signup | device.automation | Block |
| Proxy exit | network.proxy | Block (engine default) |
| Burner mailbox | email.disposable, reason disposable_email | Step-up |
| Browser clock in another country than the home IP | timezone.matches_ip: false with timezone.checked: true, reason timezone_mismatch | Step-up |
| Many profiles from one device in a day | Your own counter keyed on device.visitor_id | Step-up at 2 in 24 h, block at 5 |
| Brand-new device on the publish action | device.times_seen: 1, device.first_seen | Evidence (every real first signup looks like this) |
The first two rows need each other. Early in that run each spoofed profile had its own stable visitor id, so linking alone did not join them; after some thirty sightings the matcher stopped splitting them, but the flag had caught every full profile spoof from the first request. A plain browser is caught by the count, an antidetect browser by the flag; together, neither has to be perfect.
We chose the linked-accounts threshold; nothing measured it. Two profiles on one device is a couple sharing a tablet, a reinstall, or a profile after a breakup. Three is not a household. Our post on separating a shared family login from a resold one draws the same line.
Where the check goes
Signup creates a row; nothing is at stake until it enters discovery or the listing goes live. The evaluation goes there: after the profile exists, before it is shown, with accountId set to the profile id so the count arrives in the same response. A signup-form check runs before a profile id exists to link.
The handler below is the decision point; SENTINEL_KEY keeps the env-var name from the product's first release — the product is Maskbreak.
// After the profile row exists, before it enters discovery.
// SENTINEL_KEY is your sk_test_ key in CI and staging.
app.post('/profiles/:id/publish', async (req, res) => {
const profile = await db.profiles.get(req.params.id, req.user.id);
const r = await fetch('https://maskbreak.com/v1/evaluate', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.SENTINEL_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: req.body.token, // network layer
fingerprintEventId: req.body.fingerprintEventId, // device layer
accountId: profile.id, // unlocks linked_accounts
email: req.user.email,
tz: req.body.tz // Intl.DateTimeFormat().resolvedOptions().timeZone
})
});
const v = await r.json();
const linked = (v.device && v.device.linked_accounts) || 0;
await db.profiles.setVerdict(profile.id, {
decision: v.decision, reasons: v.reasons,
linked, visitorHash: v.device ? hash(v.device.visitor_id) : null
});
if (v.decision === 'block' || linked >= 3) {
// Same body as the review branch on purpose.
return res.json({ status: 'pending' });
}
if (v.decision === 'review' || linked === 2) {
await queue.add('profile-review', { id: profile.id, reasons: v.reasons });
return res.json({ status: 'pending' });
}
await db.profiles.setVisible(profile.id, true);
return res.json({ status: 'live' });
});Two things are deliberate. Block and review return the same body, so the operator learns nothing about which rule fired. And the verdict is written before any routing, because a profile reported in six weeks is worth nothing unless you can pull its siblings by device; the aged-account playbook makes the same point.
The escalation paths run from a terminal with the public sandbox key.
curl -s -X POST https://maskbreak.com/v1/evaluate \
-H "Authorization: Bearer sk_test_sandbox" \
-H "Content-Type: application/json" \
-d '{"token":"test_clean","email":"someone@mailinator.com"}'That is the production response on 2026-08-30, minus status, isSuspicious, ip, the legacy details mirror and evaluated_in_ms. A clean home connection plus a burner mailbox lands in review. Send test_proxy instead: decision: block, network.proxy and network.datacenter true, datacenter_asn among the reasons. Device fields need a real fingerprintEventId: use your own sk_test_ key on a staging page with the SDK.
Response ladder
Three rungs. Apps skip the middle one: a held profile is invisible to everyone but its owner, which costs a real user one verification prompt and a farm the only thing it came for.
| Rung | What happens | Evidence it needs |
|---|---|---|
| Allow | Profile enters discovery; listing goes live. | decision: allow, linked_accounts of 0 or 1, no velocity hit. |
| Shadow review | Owner sees the profile as live; nobody else does. Step-up: a photo-verification prompt or a reviewer's look at the device's siblings. | decision: review, or linked_accounts: 2, or a second profile from the device inside 24 hours. |
| Block | Same "pending" state as review, never released; the account can still log in. Siblings on the device get the same look. | decision: block (the antidetect_browser reason, or the device.automation or network.proxy flag), or linked_accounts of 3 or more, or five profiles from one device in a day. |
A VPN on its own never moves a profile off the allow rung. Travelers and expatriates sign up on VPNs; the API's timezone check stays quiet on a VPN exit for that reason (timezone.checked: false). The guide on routing on the decision and sorting on the score explains the split.
When a user reports a profile, pull every profile sharing its device hash and review them together; otherwise the farm is removed one profile at a time. Linking is per API key and hash-only on both sides; our note on where device fingerprinting stands under GDPR and ePrivacy covers the privacy-policy disclosure you still owe.
What it costs you
The platforms that publish figures publish moderation volume, not losses. Match Group says "80% of harmful accounts are proactively removed before a user ever reports them" (Match Group Trust and Safety, checked 2026-08-29). One operator's numbers, but the bill has the same shape at any size: a review queue, and profiles a real user meets before a reviewer does.
The check is one call per publish action on the free tier's 1,000 requests an hour (rate limits). It buys the fact the farm cannot change: profiles 2 through 50 share the hardware, and the hardware, or the tool hiding it, is visible before the profile is shown.
Checklist
- Evaluate at the publish action (profile shown, listing live), not only at the signup form.
- Send
fingerprintEventId,accountId(the profile id),emailandtz; no device fields without the first, nolinked_accountswithout the second. - Route on
decision. Block onblock; never onnetwork.vpnalone. - Your own rule:
linked_accountsof 2 is a step-up, 3 or more a hold. Keep a 24-hour counter perdevice.visitor_idhash; the API counts accounts, you count attempts. - No rule on
tampering_score. Usedevice.antidetect. - Return the same "pending" body for review and block; store
decision,reasonsand the visitor-id hash, and pull the siblings on a report. - Prove the paths in CI with
sk_test_sandbox:test_cleanplus a burner address returnsreview;test_proxyreturnsblock. - For marketplaces, add the listing price against the category median as your own evidence row; the farm's listings are cheap by design.
The product page for stopping fake signups covers the call and the free tier; this post is the reasoning for where it goes.
Questions people ask
- How do dating apps detect fake profiles?
- The controls most apps run, photo verification, email confirmation and IP rules, each check one thing a farm supplies on purpose: a face, a mailbox, a home address. What a farm cannot supply is a separate machine per profile. Linking profiles by device (device.linked_accounts) and flagging a browser whose fingerprint contradicts its engine (antidetect_browser) catches the shared hardware or the tool hiding it.
- Does photo verification stop fake dating profiles?
- It stops stolen-photo profiles where nobody with that face is at the phone. Tinder's check compares two posed selfies to the profile photos; Bumble's has a person review a posed selfie. Neither counts how many verified profiles one face or one device owns, so an operator who supplies a real face passes it for every profile. Treat the badge as one piece of evidence, not clearance.
- Can a residential proxy hide a fake profile farm?
- It hides the network. Each profile exits from a rented home IP in the claimed city, so network.residential is true and per-IP rules never fire. It does not hide the device: profiles on one machine share a visitor_id unless an antidetect browser fabricates one per profile, and antidetect_browser fires when the fabricated fingerprint contradicts the engine underneath. Check the device layer, and treat a residential exit as a route rather than a clearance.
- How many accounts per device should a dating app allow?
- Two linked accounts on one device is a couple sharing a tablet, a reinstall, or a second profile after a breakup, so we step up rather than block. Three is not a household. Start with step-up at linked_accounts of 2 and a hold at 3 or more, then tune on your own review outcomes. Marketplaces can be looser on the count but should hold cheap listings from a new device.
- Does the same check work for fake marketplace listings?
- Yes, with the listing's publish step in place of the profile's discovery step. The FTC describes the pattern: a listing copied from a real one or priced well under the area, a seller who cannot show it in person, and a deposit before viewing. Run the evaluation with accountId set to the seller id before the listing goes live, hold on linked_accounts of 3 or more, and add the listing price against the category median as your own evidence row.
Put the check where the attack enters
One call before signup, login or checkout returns decision, risk_score and the reasons behind them. The free tier is 1,000 requests an hour, no card required. Start with <a href="/vpn-detection">VPN detection</a> and <a href="/proxy-detection">proxy detection</a>, the network layer most attacks lean on.