Flow-Based Anomaly Detection: When Proxies Can’t Hide Consistency


David
July 7, 2025


Flow-Based Anomaly Detection: When Proxies Can’t Hide Consistency
I keep thinking about how easy it used to be. You’d grab a fresh proxy, fire up a browser profile, check your headers in one of those online tools, maybe patch your canvas just for luck, and you’d be good to go. That was the game. It felt technical, but looking back, it was a lot like trying to win at poker by changing shirts every hand.
Fast-forward a couple years and now it’s not about the hand you’re holding, it’s about how you play the whole night. Everyone in anti-botland figured out that a single snapshot means nothing if your next five moves all rhyme. You could rotate your IP every page, change your browser fingerprint on every visit, but if you move the same way every time - same path, same tempo, same mistakes (or lack of them) - you’re dead in the water. Not at first, but after a couple laps around the track, you’re definitely going to start noticing those mysterious “your session expired” messages. Or worse, nothing obvious happens at all - you just start slipping quietly to the edges. A little less access, a little more friction, and before you know it, you’re a ghost.
Where the Old Playbook Falls Down
I’m not going to pretend I saw this coming. Nobody did. I spent a year or two thinking if I just made my fingerprints unique, I’d be invisible. But “unique” and “weirdly repetitive” aren’t opposites. I’ve burned whole proxy pools not because the IPs were dirty, but because my flow - the way my bots stepped through a session, the rhythm of my page loads, my uncanny click cadence - made me stick out like I was waving a sign.
I remember running a supposedly randomized pool across dozens of social media profiles. Fresh browser every session, headers randomized, IPs from ten countries. But every single “user” clicked through the same steps in the same order, at almost the exact same pace. Sure, sometimes we’d swap in a “random” scroll or a pause before a button, but it was always just… too… clean. Too even. And that’s exactly what flow-based anomaly detection is looking for - the stuff that’s not in the fingerprint, but in the timeline.
They don’t care what mask you’re wearing. They care about how you dance.
The Story in the Gaps
So what’s flow, anyway? It’s not just click paths and request timings. It’s the little stuff. How you hesitate between clicking and typing. The lag after a page load, the scroll before you decide to engage. Real users are a mess. They check their phone, tab away, reread something, fumble for coffee, sometimes leave for an hour before coming back. That’s the soundtrack of the web.
Bots? They have habits. Even when they try to be random, it’s always the same flavor of random. Five second gap, load, click, next, scroll, done. Maybe throw in a “human” delay - but if you chart it, it’s a heartbeat. And heartbeats, as every bot hunter knows, are easier to spot than faces.
What Flow-Based Detection Actually Sees
Let’s break it out, because nobody ever seems to list this stuff for real:
- Time between actions - No two users have the same tempo, not across a whole site. But bots? Once the script is set, the gaps are identical, even with random jitter.
- Navigation order - Real people get lost. They double back, they check FAQs, they jump to the wrong page. Bots rarely do unless you force them.
- Resource requests - A human browsing loads things in clumps, leaves half the resources for lazy load, sometimes never even triggers the analytics call. Bots are eager, hit everything, every time, in the same order.
- Focus and blur - Who never switches tabs, even once? Who never gets distracted by Slack, WhatsApp, a barking dog? Bots. That’s who.
- Mistakes and recovery - Most sessions don’t go in a straight line. Humans click the wrong button, back out, reload, maybe even rage-quit and try again. If your flow has no zig-zags, you’re not hiding, you’re sticking out.
I got called on this in the dumbest way - running what I thought was a sophisticated “scraper” for a private forum. All it did was visit the landing page, click through, check a few posts, and leave. But the click pattern was always the same - and the site started rate limiting, then finally cut off the whole ASN. I dug into the logs and the only tell was timing. My sessions moved with a precision no real person would bother with.
Real Browsing is a Mess
That’s what the models hunt for - neatness, regularity, symmetry. The same way you can tell a room’s been cleaned by a robot vacuum, not a teenager. It’s too perfect, too clean, too fast, too quiet.
Ask anyone who runs ops at scale. The hardest thing to mimic is boredom. Or distraction. Or the fact that real people don’t just interact, they also stop interacting. That’s the gap most stacks leave wide open - bots finish too fast, too efficiently, with no “life” in between. If you never make a mistake, never pause, never get lost, you’re not invisible. You’re a flashing warning light.
The Illusion of Randomness
I used to think you could just add more random delays. Or shuffle the navigation order. And for a while, that worked, at least against the low-end stuff. But flow-based systems don’t look at any one gap, they look at the whole timeline. And bots are really bad at being random in a way that feels like someone actually living.
Here’s what I’ve tried (and how it usually failed):
- Jitter delays between clicks - sure, but every session gets the same flavor of jitter.
- Shuffle click order - but not really; it’s always the same small set of possible routes.
- Simulate “think time” - which means every user waits just long enough to look natural, but it’s never as chaotic as real people.
- Fake “focus lost” - a good step, but bots don’t alt-tab to Slack and forget to come back for five minutes.
Real change happened for me when I stopped scripting “randomness” and started scripting “boredom.” Like, literally have some sessions just go off and browse a different part of the site for a while. Or leave a session idle for twenty minutes and then come back and finish. Once I did that, the flow got harder to cluster, and my sessions stopped getting grouped and burned.
What Proxied.com Had to Learn
It took us a few painful months to figure this out in our own network. We’d focused so much on fresh IPs, diverse browser stacks, entropy all over the place. But in the logs, you could see it - every session had the same pace. A beautiful rhythm, like a parade. And it cost us.
Now, we run mess by default. Our proxy exits don’t just switch IP, they inject “life” - real distraction, tabs lost and found, pauses that don’t make sense, sometimes even sessions that start and never finish. Our best sessions look like they were run by someone on bad WiFi with a meeting starting in ten minutes. You can’t cluster that, because nobody would want to.
Some People Will Tell You "Clean" Wins
I get it - the urge to tidy everything up. But the dirt is what keeps you safe. Next time you build a session flow, try making it uglier, not prettier. If it feels like a mess, that’s the point.
Little things that help:
- Don’t reuse navigation templates. Build lots of possible flows, even ones that “don’t make sense.”
- Sometimes scroll up, sometimes down, sometimes not at all.
- Forget about “optimal” timing. Let some actions happen fast, others slow, others not at all.
- Build in real mistakes. Have your script click the wrong button, or get a 404, and deal with it.
- Let sessions get distracted. If your bot never leaves a tab idle, never checks out, never closes before finishing - you’re missing something.
- Sometimes end a session halfway. That’s what users do.
Don’t Rely on Rotation Alone
Rotating IPs is easy. Rotating your story is hard. But if you don’t do both, you’re only hiding from the simplest checks.
Every session should feel like a different day. Monday morning rush, Tuesday evening boredom, Friday chaos - your flows should look like all three.
Flow-based anomaly detection doesn’t care about your fingerprints. It cares about your soul. Or, at least, the digital equivalent.
If your bots always move the same way, you’re not being stealthy - you’re just dancing in formation for the bouncer.
Final Thoughts
There’s no script for being human. Just make sure your sessions don’t look like they’ve been scripted. If it feels uncomfortable - like you’re letting go of control - you’re on the right track.
Because nobody gets flagged for being a mess. Only for being too tidy, too neat, too damn consistent.