How I Dealt with Free Trial Abusers in SaaS

"New user signed up" logs screenshot
That's kinda sus 🤨

If you’re running a project that offers free trials or limited use of certain features, you’ll inevitably run into users who try to extend their free usage as much as possible.

Here’s how I tackled the issue.

CAPTCHA

We all encounter CAPTCHA in some form every day on the internet. I usually go with Cloudflare Turnstile – it’s like Google’s reCAPTCHA, but from Cloudflare.

It lets legitimate users through almost instantly, without forcing them to pick out bicycles from images. It also lets bots through if they’re using a decent ChromeDriver. Still, a good portion of would-be abusers will drop off at this stage.

I’m against using any form of security that creates friction for potential customers, so I won’t suggest implementing CAPTCHA with distorted characters or making users solve integrals.

Prove that you are not a robot: select all squares with Convergent improper integrals
💭 I still don’t understand what all these symbols mean.

Emails

In my projects, I use email-based registration, with optional Google or GitHub logins.

You could take a radical approach and restrict registration to social networks or phone numbers only, but I believe this would hurt conversion rates and drive away potential customers (the same goes for implementing whitelists of email domains). Plus, if the value of your free product outweighs the cost of setting up a social media account or getting a throwaway SMS number, abusers will still find a way.

When it comes to email, bad actors can use disposable email services. There are thousands of domains for receiving such emails (seriously, here’s a regularly updated list).

There are many repositories with lists of these domains and services that check if an email is disposable: 1, 2, 3, 4. I use 7c/fakefilter and even periodically request that they add new services for scanning. Like CAPTCHA, this filters out most abusers, but unfortunately, these services are growing, and it’s impossible to track every domain.

Additionally, abusers can use legitimate services like Gmail, where creating an email address can cost between $0 and $0.1. Here, we’re out of luck too.

IP Addresses

The simplest thing you can do with IP addresses is set rate limits for sensitive actions like account registration.

You can also use IP lookup services that provide detailed information, including whether an IP is known as a public proxy or VPN server. You can simply log this data or complicate registration for users from such addresses. I use proxycheck and block registrations from addresses with a risk score of 67 or higher, asking users to disable their VPN if needed.

This isn’t a perfect solution either, as abusers can use rotating mobile or residential proxies that look like normal user traffic.

Book: How to calculate by IP and punch his face
💪 The most effective way to solve the problem

Fingerprints

There are libraries and services that allow you to fingerprint a user’s browser based on hundreds of parameters (from simple ones like user-agent and time zone to more intricate ones like fonts installed on their OS). Example: FingerprintJS.

This tech is undoubtedly impressive, but in my experience, largely ineffective. If a user has bypassed your CAPTCHA or Turnstile, they’re probably using undetected-chromedriver or something similar. This creates a separate session, leading to a unique fingerprint. Just as if you created a new Chrome profile.

By the way, you can test how unique your fingerprint is compared to others: Am I Unique?

When you enter incognito mode... FBI: All right then, keep your secrets.
👀 Fun fact: your incognito mode fingerprint is the same as your regular fingerprint

The Human Element

Alright, let’s assume the abuser used trusted IPs and email addresses, passed CAPTCHA, and gained access to your service. And they did this hundreds, thousands, or even hundreds of thousands of times.

In my case, one of my projects is an API, and free trial abusers’ main goal is to get an API key for 100 free requests.

The most common scenario: it’s hard to detect the abuser at registration, but once they start using the key, it becomes obvious. Why? Because they make requests from the same server IP. 🤡

A simple script that counts the number of keys used from a single IP and automatically blocks violators has weeded out plenty of creative users.

Conclusion

You can’t block everyone :)

You could endlessly come up with new security measures, but it’s far more reasonable to focus on improving your service and boosting sales.

If you’re just launching your SaaS, I’d recommend sticking with CAPTCHA and blocking disposable email addresses. And if your product isn’t metrics-driven and free trials are hurting your budget, you might want to consider ditching free trials in favor of an affordable starter plan.