All articles Fraud & ATO

Stopping Trial Abuse When You Don't Bill on Stripe

Most advice about free-trial abuse quietly assumes you run Stripe. “Turn on Radar,” “dedupe on card fingerprint,” “write a rule on the payment method.” That’s fine if Stripe sees every trial. Plenty of teams don’t work that way:

  • You sell through a merchant of record like Paddle or Lemon Squeezy, and their checkout owns the payment.
  • You’re a mobile app and trials run through App Store or Google Play subscriptions.
  • You’re B2B and invoice after a sales-assisted trial.
  • You’re in a market where customers pay through a local gateway, bank transfer, wallet or cash voucher, and cards are the exception.
  • Your trial asks for no payment details at all, because that converts better.

In every one of those setups, the payment layer either never sees the trial or sees it too late. This post is about where to put the check instead.

Why payment-side tools miss trial abuse

Payment fraud tools answer a specific question: is this payment legitimate? A stolen card, a card-testing run, a mismatched billing address. They’re good at that question. Trial abuse asks a different one: has this person already had their free month?

Those questions come apart in three ways.

No-card trials never reach the payment layer. If signup is email and password, there is no payment event to score until conversion, which for an abuser never comes. They take the trial and leave.

Fresh valid cards look clean. When a trial does require a card, the abuser uses a different one each time: a virtual card, a prepaid card, a family member’s card. Each is a real card that authorizes fine. Nothing about the payment is fraudulent; the abuse is in the repetition.

The merchant of record owns the data. With Paddle or an app store, the payment signals live in their system. You get a webhook that a subscription started. You don’t get to write a rule that says “decline if this device had a trial last week.”

So the signal you need isn’t in billing. It’s at the front door.

The device is the stable key

What a repeat trialist changes between attempts is cheap: email address, card, IP (through a VPN or mobile network), cookies. What’s expensive to change is the device. Most people farming trials are one person with one or two laptops and a phone.

A device identifier that survives cleared cookies and private windows turns “a new signup” into “the fourth signup from this browser.” Prynt returns that as a visitorId, and on the server it returns accountsOnDevice: every account id you’ve attached to that device.

The check runs at account creation, which you own regardless of billing:

// browser, on the signup page (agent loaded from https://api.pryntid.com/cdn/prynt.umd.js)
const prynt = await Prynt.load({ apiKey: 'pk_live_…' });
const { requestId } = await prynt.identify({ tag: { action: 'signup' } });
// send requestId with the signup form
// server
import { PryntServer } from '@prynt/node';
const prynt = new PryntServer({ secretKey: process.env.PRYNT_SECRET_KEY });

const event = await prynt.getEvent(req.body.requestId);
if (event.decision === 'block' || event.accountsOnDevice.count >= 1) {
  return res.status(409).json({ error: 'trial_already_used_on_this_device' });
}
const user = await createUser(req.body);
await prynt.updateEvent(req.body.requestId, { linkedId: String(user.id) });

Nothing in that code knows or cares how you bill. The updateEvent call attaches the new account to the device, which is what lets the next attempt see it.

Where to check for each billing model

The principle is “check before you give away something that costs you.” Where that moment falls depends on the stack.

Merchant of record (Paddle, Lemon Squeezy)

Check at account creation in your own app, before you open the overlay checkout. If you start the trial from a webhook, store the requestId on the pending user and decide when the webhook arrives. Don’t rely on the checkout to dedupe; it sees a customer, not a device.

App store subscriptions

Introductory offers are generally limited per store account, but a second store account on the same phone is easy. If your app creates its own account at signup, run identification through the mobile SDKs (iOS, Android, Flutter and React Native are available) and apply the same limit to your account, not the store’s. On mobile, also watch for app cloners; emulator and cloned-app signals are the related environment checks.

Invoicing and sales-assisted trials

The abuse here is usually a competitor or consultant opening several workspaces. Run the check on the self-serve signup and route over-limit devices to a sales conversation instead of a refusal. That’s a feature, not friction: a prospect who wanted a second workspace should be talking to you anyway.

Local gateways and no-card trials

This is where device checks matter most, because there’s no card to fall back on at all. We cover it in depth in free-trial abuse in LatAm SaaS.

Respond in tiers, not with a wall

A refused signup is the strongest response and the one most likely to hurt a real user. Most teams do better with three tiers:

  1. Allow: first account on the device, no automation signals. Zero friction.
  2. Verify: the device already has an account, or Prynt returns challenge. Create the account but hold the trial until a phone OTP or a card is added.
  3. Block: Prynt returns block, or the device is well past your limit.

Prynt’s Supabase, Clerk, Auth0 and Express recipes implement exactly these tiers with one shared policy (allow, flag, verify, block). The default blocks at two other accounts on the device and flags rather than refuses when a requestId is missing, so privacy-focused users who block scripts can still sign up.

What this doesn’t replace

If you do take cards, keep your processor’s payment fraud protection on. Stolen-card checkouts and card testing are real and separate problems; see subscription billing fraud. The device check adds the one thing billing can’t provide: memory of who already had a trial.

For the full trial-farming playbook, read how to stop free-trial abuse. The Free plan on the pricing page covers 20k identifications a month with no card, which is enough to run the check in flag-only mode and see how many repeat devices you’ve been giving trials to.

Try it free

Prynt is device intelligence with a free tier — visitor IDs, bot & fraud Smart Signals, and behavioral biometrics, powered by a cross-site network. Start free.

Keep reading