This tool produces random 3- or 4-digit security codes for test data. It is worth being precise about what that means, because most people searching for a “CVV generator” want something else: a way to work out the CVV that belongs to a particular card number.
That is not possible. Not with this tool, not with any tool. A CVV is computed by the issuing bank from the card number, the expiry date, the service code, and two secret cryptographic keys that only the issuer holds. Without those keys there is no calculation to perform — and there is no shortcut, no leaked algorithm, and no lookup table. This is by design; it is the entire reason the code exists.
Test data only
CVV Generator
Random security codes at the right length for the network you pick. Generated in your browser, from nothing but a random number source.
Codes may repeat. Three digits give a thousand possibilities, so a batch of any size will contain duplicates — that is what randomness looks like, not a bug.
How a real CVV is actually generated
The process is not secret. It is documented in payment hardware manuals and implemented in every issuer’s card-management system. Knowing it does not help you derive anything, and seeing why is the most useful thing on this page.
The inputs
- The primary account number — the card number itself
- The expiry date
- The service code, three digits that encode how the card may be used: whether it works internationally, whether a chip must be used where available, whether a PIN is required
The keys
- A pair of Card Verification Keys, held in the issuer’s hardware security module
- The pair belongs to the issuer, typically per BIN range rather than per card
- They never leave the HSM. Not to an application, not to a backup, not to staff
The process, at a level that explains without enabling
- The account number, expiry and service code are concatenated into a fixed-width block.
- That block is encrypted under the key pair using Triple DES.
- Digits are filtered out of the result.
- The first three of them — four for American Express — are the security code.
Every input except the keys is printed on the card. The keys are what make the code unforgeable. That is the whole security model: anyone can read your card number, but only your bank can compute the code that goes with it.
CVV1, CVV2 and iCVV
The same machinery produces three different values, and confusing them is a real source of integration bugs:
- CVV1 is encoded in the magnetic stripe. It travels with a swipe and proves the stripe is genuine rather than written by hand.
- CVV2 is the code printed on the card. It never appears in the stripe or the chip, which is precisely why quoting it is treated as weak evidence that someone held the card.
- iCVV lives in the EMV chip and is deliberately different from CVV1, so data lifted from a chip transaction cannot be replayed as a counterfeit magnetic stripe.
What separates them is the service code fed into the calculation, not the algorithm. That detail is why a system that validates one of them against another’s expected value rejects perfectly good cards — and why “the CVV” is an ambiguous phrase in any specification that does not say which one it means.
Network naming
| Network | Name | Digits | Location |
|---|---|---|---|
| Visa | CVV2 | 3 | Back, signature panel |
| Mastercard | CVC2 | 3 | Back, signature panel |
| American Express | CID | 4 | Front, right of the card number |
| Discover | CID | 3 | Back |
| JCB | CAV2 | 3 | Back |
| UnionPay | CVN2 | 3 | Back |
| Diners Club | CVV | 3 | Back |
| Troy | CVV | 3 | Back |
The American Express row is the one that breaks forms. A
field with maxlength="3" silently truncates a valid CID, the payment fails verification, and
the error surfaces as a generic decline that nobody traces back to the input. Length must
follow brand detection, and brand detection has to run as the user types rather than on
submit. Visa and Troy are three digits, as
is everything else in the table.
Why you cannot derive a CVV
Four beliefs come up repeatedly. All four are wrong, and each is wrong for a different reason.
“There is an algorithm, it is just secret.” The algorithm is public. It is described in HSM documentation and implemented in commercial card-management software. Secrecy lives entirely in the keys, which is the correct place for it — a system whose security depends on the algorithm staying hidden is broken by definition. Knowing the steps gets you nowhere without the key pair.
“There must be a formula, like Luhn.” No. Luhn is a checksum: it takes only the number as input, contains no secret, and anyone can compute it — which is why it catches typing errors and stops nothing else. A security code is closer to a message authentication code. It exists specifically so that possessing the number is not enough to produce it.
“You could brute-force it.” Three digits is a thousand possibilities, which sounds tractable and is not. Issuers block a card after a handful of wrong codes, acquirers and networks rate-limit and score repeated attempts, and the pattern is one of the most heavily monitored signals in card fraud detection. Beyond the mechanics: attempting it against someone else’s card is unauthorised access, and it is a criminal offence in essentially every jurisdiction.
“Leaked data sets contain CVVs.” PCI DSS prohibits storing the security code after authorisation — not “prohibits storing it unencrypted”, prohibits storing it at all. In version 4 this is Requirement 3.3.1, which was Requirement 3.2 under version 3.2.1. So a data set containing security codes came either from a non-compliant system or from phishing and skimming, where the code was captured as it was typed. In every case it is stolen data, and in most cases it is stale.
What this generator is for
- Filling the security-code field in test card data, so a fixture is a complete record
- Testing that field length follows the detected brand — three digits, four for Amex
- Confirming the field accepts digits only, and rejects spaces and letters
- Producing bulk values for seeding test databases
- Proving the code never reaches your logs or your storage
That last one is a compliance test, not a formality:
// Assert that the security code never reaches your logs or your database
it('does not persist the security code', async () => {
const cvv = '742';
await submitPayment({ number: TEST_PAN, expiry: '12/29', cvv });
const stored = await db.payments.findLatest();
expect(JSON.stringify(stored)).not.toContain(cvv);
const logs = await readAppLogs();
expect(logs).not.toContain(cvv);
});
Use a distinctive value rather than a common one — 742 is easier to find in a haystack than
123, and a code that also appears as a substring of the test card number will give you a
false failure. Run the same assertion against error reports and analytics payloads, which is
where these values usually escape: not through the database, but through an exception
handler that serialises the whole request body.
CVV and PCI DSS
The security code belongs to a category the standard calls sensitive authentication data, alongside PIN blocks and full magnetic-stripe contents. The rule is short: it may be handled during authorisation and must not be retained afterwards, and encryption does not create an exception. Only issuers and organisations supporting issuing services may hold it, because they are the ones who have to.
Three practical consequences:
- Storage is the easy part. Almost nobody deliberately writes the code to a database. It escapes through logs, stack traces, crash reports, request-replay tooling and analytics. Redact at the boundary, not at each call site.
- Test environments are in scope for the habit, if not the audit. Never move real card data into staging. That is what synthetic values like the ones above are for, and the test card numbers reference covers the sandbox codes each gateway expects — some processors treat the code as a trigger, so an arbitrary value there will not behave as you assume.
- The best architecture never sees it. Hosted fields and client-side tokenisation keep the code inside the processor’s iframe, so it never reaches your servers and the question of retaining it never arises.
PCI DSS for developers covers the scope rules in full. The standard itself is published by the PCI Security Standards Council.
The requirement numbering above were last checked against provider documentation on . Providers do change what they publish — the official link beside each claim is authoritative.
Related tools and guides
Generate complete records — number, expiry and code together — with the all-network generator, or build numbers on a prefix of your own with the BIN generator. The tool directory lists everything else, and the FAQ covers what a Luhn-valid number does and does not prove.