Automated scam checking on Leboncoin: harder than it looked
The problem that kept bugging me
I'm sick of fake listings, and I wanted to see how to tackle the problem in a white-box, above-board way while still being scalable. A real challenge.
One marketplace, not five
The first decision, before writing a single line of code: focus on Leboncoin only. The original idea aimed wide — Leboncoin, Vinted, eBay, Facebook Marketplace — but each platform has its own page structure, its own protections. Trying to cover all of them from day one is the surest way to cover none of them properly. One marketplace, one signal that genuinely works on it, and we'd widen the scope later if it proved worth it.
Before scraping anything at all
Before writing a single line, two quick checks:
- Leboncoin's robots.txt is unambiguous: "it is forbidden to use search robots or other automated methods to access Leboncoin.fr."
- a plain HTTP request to a public page on the site got an immediate 403.
And, more tellingly: the only real competitor in this space, Shady AD, which already covers Leboncoin, eBay, and Vinted, isn't a server-side scraper. It's a browser extension. The competitor had already settled the question for us — their answer carried more weight than any architectural hunch of ours.
The entire architecture changed before a single line of code was written: a browser extension that reads the page the user has already opened themselves, on a simple click, rather than a server fetching pages on its own.
The prototype
A Chrome and Firefox extension, triggered only on click — no automatic scanning of every listing visited, to stay light on both the permissions requested and the cost of API calls. A minimal backend, one signal to start with: does the listing's photo have an exact match somewhere else on the web?
The first real test broke it immediately
First run on a real listing: a Hi-Fi amplifier. Result: very high risk, the photo showing up identically on dozens of sites.
Except it almost certainly wasn't a scam. Even in strict mode ("exact matches"), Google Lens was returning different photos of the same amplifier model as if they were identical — the detection itself isn't precise enough to tell a genuine copy apart from a merely similar photo of the same product.
Two adjustments later (filtering down to domains that actually matter, then only counting genuinely identical matches instead of "similar product"), the signal got more honest. But Google Lens has its own limits, and it still triggers false positives on this kind of supplier or manufacturer photo — not something a simple threshold tweak fully solves.
What's still left to build
The photo signal alone isn't enough:
- go beyond Google Lens on images, since its own limits are exactly what's causing the false positives seen so far,
- run the description through a proper check (DeepL translation included) to spot a copy-paste from a forum or another listing,
- compare the listed price to a secondhand market price — if it's more than 50% below the average, that alone is already a strong signal,
- look at the seller's review count — an account with only one or two reviews becomes a signal on its own, almost automatically.
What I take away from this
One real test case reveals more design flaws than an hour of architecture debate. Here, it happened twice in the same project, at two different levels: first on the legality of accessing the data, then on the reliability of the signal itself.
And one big limit no amount of iteration will lift, unfortunately: without access to Leboncoin's internal data — IP address, phone number, seller email, login times — the tool stays a black box.
Basically, a scalable, automated, white-box product for spotting scams strikes me as difficult, if not impossible, to make truly robust. Maybe the only real answer is to go through the marketplace's own payment system, which acts as a buffer and insurance when something goes wrong.
Either way, that's what I'd tell anyone non-technical: pay through the platform's own payment system to stay as protected as possible.