Stripe's published sandbox card numbers are the top pick for most development teams, because one documented set covers approvals, soft and hard declines, 3D Secure challenges, and several card networks. The criteria behind that pick are documentation quality, coverage of failure paths, isolation from live processing, and how stable the values are inside an automated test suite.

What a credit card test number is

A test card number is a card number that a payment processor sets aside for sandbox use. It passes the same format checks as a live card, including the Luhn checksum and the issuer identification prefix, so your form validation, tokenization step, and webhook handling behave the way they will in production. No real account sits behind it, and every charge against it is simulated inside the gateway's test environment.

That is the point. You want to exercise the code path that runs when a card is declined for insufficient funds without moving money or touching a cardholder account. Test numbers give you that path on demand.

Top pick: the Stripe sandbox card set

Stripe's testing documentation is the reference set worth starting from, even if you later switch processors, because the values are stable and each one maps to a specific outcome.

  • 4242 4242 4242 4242, Visa, any charge succeeds.
  • 4000 0000 0000 9995, Visa, declines with an insufficient funds code.
  • 4000 0025 0000 3155, Visa, triggers a 3D Secure authentication step.
  • 5555 5555 5555 4444, Mastercard, any charge succeeds.
  • 3782 822463 10005, American Express, any charge succeeds.
  • 6011 1111 1111 1117, Discover, any charge succeeds.

In test mode the gateway accepts any future expiration date and any CVC value, which keeps your fixtures short.

Pros

  • Decline and authentication cases come from the processor, so you are not writing error handling against a guess.
  • The same numbers work across server SDKs, mobile SDKs, and hosted checkout pages.
  • The values have been stable for years, so they can live in a fixture file without churn.

Cons

  • They behave as documented only inside that vendor's sandbox.
  • Coverage of niche networks and regional schemes is thin.
  • Test mode can hide differences from a live account, such as issuer rules and risk checks.

Use this set when you are integrating a gateway, writing an automated checkout test, or reproducing a support ticket that quotes a decline code.

Second option: PayPal and Braintree sandbox cards

PayPal's developer documentation covers Braintree sandbox values, including 4111 1111 1111 1111 for Visa, 5555 5555 5555 4444 for Mastercard, 3782 822463 10005 for American Express, and 6011 1111 1111 1117 for Discover. The overlap with the Stripe set is not a coincidence. These are reserved ranges processors keep out of live circulation.

Pros

  • Matches the sandbox you ship against when PayPal or Braintree is in your stack.
  • Covers the four major networks for basic success-path testing.

Cons

  • Fewer built-in decline scenarios, so some errors have to be forced through API parameters instead.
  • Documentation is split between PayPal and Braintree pages, which slows lookups.

Use this set when your integration is Braintree-first, or when you want a second vendor to confirm your abstraction layer handles more than one processor.

Third option: generating your own numbers for format tests

If all you need is proof that a form rejects malformed input, you do not need a gateway at all. Compute a valid Luhn check digit from a prefix such as 4000 or 5555 and feed it to your validator.

Pros

  • No account, no network call, no vendor dependency.
  • Runs in unit tests in milliseconds, including offline CI.

Cons

  • It proves nothing about how a processor responds, so it cannot replace an integration test.
  • A generated number that happens to match a live account is a real hazard if it ever reaches a live endpoint.

Use this approach for client-side validation and regression tests on the Luhn routine itself, and keep it away from anything that talks to production.

How to choose

  1. Start with the sandbox set published by the processor you are integrating. That is the only set with documented behavior.
  2. Map each test number to a test case: success, insufficient funds, expired card, authentication required.
  3. Keep the values in one fixture file, with a comment naming the source and the date you copied it.
  4. Add a generated Luhn number for pure format tests so unit tests stay fast.
  5. Run the same suite against a second gateway if you plan to support multiple processors.

Where test numbers stop being appropriate

A test number is a test number only inside a sandbox. Pointing any card number you did not receive from an issuer at a live payment endpoint is card fraud, whether or not the account is real, and it carries legal exposure. Merchant agreements, network rules, and PCI DSS all treat live card data as a controlled asset that needs a defined business need, secure storage, and audit trails.

That is also why a full card number, expiration date, and CVV should never go into a ticket, a chat thread, or a test fixture. Values published by a processor for sandbox use are the exception, because no account sits behind them. Anything else is not a test number, and no amount of sandbox labeling makes it safe to use.