CVV vs CVC vs CID: card security codes explained
CVV, CVC, CID, CAV2, CVN2 — the three or four digits that every online checkout asks for go by a different name on almost every card network. They all do the same job. This guide explains what the code proves, how issuers create it, how to handle it in a payment form and what PCI DSS says about keeping it.
Key takeaways
- CVV2 (Visa), CVC2 (Mastercard), CID (American Express, Discover), CAV2 (JCB) and CVN2 (UnionPay) are names for the same thing: a code that shows the payer has the card.
- American Express prints a 4-digit code on the front; the other major networks print 3 digits on the back.
- Issuers derive the code with secret keys, so a merchant can only check its length. Whether it is correct is decided by the issuer during authorization.
- PCI DSS Requirement 3.3.1.2: the code may be collected for authorization but must never be stored afterwards, not even encrypted.
On this page
Every card-not-present checkout asks for the same short code, but the label changes with the card: Visa says CVV, Mastercard says CVC, American Express says CID. Developers then have to decide how long the field should be, what to validate and what may be logged. The answers are simpler than the alphabet soup suggests.
What a card security code is for
The card security code is a short value printed on the card but not contained in the card number. When a customer types it into an online checkout, the issuer can compare it with the value it expects for that card. A match is evidence that the payer has the physical card — or at least saw it — rather than just a list of card numbers.
That evidence matters most for card-not-present payments: e-commerce, apps and phone orders, where nobody can inspect the card. It is one layer of fraud prevention alongside address verification (AVS) and 3-D Secure, not a complete defense: a phishing page can steal the code together with the number.
The names used by each network
Every network gives the code its own name, but the function is the same. Generic terms you will also see are CSC (card security code) and CVD (card verification data).
| Network | Name | Stands for | Digits | Where |
|---|---|---|---|---|
| Visa | CVV2 | Card Verification Value 2 | 3 | Back |
| Mastercard | CVC2 | Card Validation Code 2 | 3 | Back |
| American Express | CID (also 4DBC) | Card Identification Data / 4-Digit Banking Code | 4 | Front, above the number |
| Discover | CID | Card Identification Data | 3 | Back |
| JCB | CAV2 | Card Authentication Value 2 | 3 | Back |
| UnionPay | CVN2 | Card Validation Number 2 | 3 | Back |
| Diners Club | Security code | — | 3 | Back |
In your UI, a neutral label such as “Security code” plus a small hint (“3 digits on the back, 4 on the front for Amex”) works for every brand. Switch the hint once you have detected the brand from the card number’s prefix — the card number format page lists the prefixes.
CVV1, CVV2, iCVV and dynamic codes
The “2” in CVV2 and CVC2 is there because there is also a version 1. Several related values exist, and each is used in a different channel:
| Value | Where it lives | Used for |
|---|---|---|
| CVV1 / CVC1 | Encoded in the magnetic stripe | Card-present swipe transactions, checked by the issuer |
| CVV2 / CVC2 / CID | Printed on the card | Card-not-present payments typed by the customer |
| iCVV | Chip data | Chip and contactless transactions; differs from CVV1, so chip data copied onto a magnetic stripe does not carry a valid stripe code |
| Dynamic CVV | Banking app or, on some cards, a small display | Card-not-present payments with a code that changes over time |
The printed code and the stripe value are calculated with different inputs, which is why reading a magnetic stripe does not reveal the code you type online. With dynamic CVV, some issuers no longer print a fixed code at all; the cardholder gets a fresh one in their banking app. For a checkout this changes nothing — you still collect three or four digits and pass them to the gateway.
How issuers generate the code
The code is not computed from the card number with a public formula the way the Luhn check digit is. The issuer derives it cryptographically from the card number, the expiry date and a service code, using secret keys kept in hardware security modules. Different service codes produce the stripe value, the printed value and the chip value from the same card data.
Two practical consequences follow:
- A merchant cannot tell whether a code is correct. Only the issuer, holding the keys, can verify it during authorization.
- A random code that a card generator produces is just three or four random digits. It fits the field and nothing more.
With only 1,000 possible three-digit values, the protection depends on issuers and merchants limiting repeated attempts. That is why guessing security codes is a hallmark of card-testing attacks, and why velocity limits belong next to every payment form.
Validating the security code in a form
Client-side validation can only check the shape of the value. Keep it simple and brand-aware:
- Digits only, as a string. Codes can start with zero (
042), so never convert them to a number. - Length by brand. Four digits for American Express, three for Visa, Mastercard, Discover, JCB, Diners Club and UnionPay. Before the brand is known, accept three or four.
- Correct input hints. Use
inputmode="numeric"for a numeric keypad andautocomplete="cc-csc"so browsers and password managers can fill it. - Don’t mask it as a password field. Customers mistype hidden digits; a plain text field with a short length is enough on the payment page.
<label for="cc-csc">Security code</label>
<input id="cc-csc" name="cc-csc" inputmode="numeric" autocomplete="cc-csc"
maxlength="4" pattern="[0-9]{3,4}" required>
<script>
// brand comes from your card-number detection: 'amex', 'visa', 'mastercard', ...
function cscError(value, brand) {
const len = brand === 'amex' ? 4 : brand ? 3 : null;
if (!/^[0-9]+$/.test(value)) return 'Use digits only';
if (len && value.length !== len) return `Enter the ${len}-digit security code`;
if (!len && (value.length < 3 || value.length > 4)) return 'Enter 3 or 4 digits';
return null; // well formed; the issuer decides whether it matches
}
</script>If you use a hosted payment field from your gateway (Stripe Elements, Braintree Hosted Fields, Adyen Components and similar), the code never touches your page’s JavaScript or your servers. That is the simplest way to keep it out of your systems entirely.
Storage: the PCI DSS rule
The card verification code is sensitive authentication data under PCI DSS. The PCI Security Standards Council states that merchants may request it from cardholders, but PCI DSS Requirement 3.3.1.2 strictly prohibits storing it after authorization — even if it is encrypted.
What that means in practice
- Collect it only for an authorization and discard it as soon as the authorization completes.
- Not for card-on-file or recurring payments. The Council’s FAQ says codes are not needed for those transactions and storage for these purposes is prohibited. A customer’s permission does not change this.
- Watch logs and tooling. Request-body logging, error trackers, analytics, support tickets and database backups are the usual places a code ends up by accident. Filter
cvc,cvvandcscfields before anything is written. - No “temporary” storage. A process that claims to delete the code but can still retrieve it for later authorizations is storage.
Re-asking is allowed, keeping is not
Some merchants ask returning customers to re-enter the security code for a saved card as an extra risk check. That is fine: the code is collected for that specific authorization and discarded afterwards. Keeping it so customers don’t have to re-enter it is not.
For the wider picture — why real card data, including codes, should never be in development and test systems — see Test data and PCI DSS.
What the issuer’s answer looks like
When you send a code, the issuer returns a separate result for it alongside the approve-or-decline decision. Gateways normalize that result; Stripe, for instance, reports cvc_check as pass, fail, unavailable or unchecked. Depending on the issuer and your gateway settings, a mismatched code can produce an outright decline, or an approval with a failed check that your own rules then reject.
- Mismatch: ask the customer to check the code, and count the attempt towards your velocity limits.
- Unavailable: the issuer did not check it. Decide whether to accept based on other signals.
- Not sent: the check is skipped. Stripe notes that if you omit the code, the check cannot fail — so require the field if your fraud rules depend on it.
Testing security code failures in a sandbox
Most sandboxes accept any code of the correct length, so the happy path is easy. To test the failure path, each gateway documents a specific card or trigger. These come from the official documentation listed on our test card numbers pages:
| Gateway | How to simulate a CVC failure |
|---|---|
| Stripe | Card 4000 0000 0000 0127 declines with incorrect_cvc; 4000 0000 0000 0101 fails the CVC check (send a CVC value) |
| Checkout.com | Card 4734 8689 5873 3862 returns 200N7, decline for CVV2 failure |
| PayPal | Name on card CCREJECT-CVV_F |
| Braintree | CVV 200 (CID 2000), with CVV rules enabled in the sandbox |
| Adyen | holderName set to CVC_DECLINED |
| Square | CVV 911 |
| Authorize.net | Card code 901 |
Check that your UI shows a clear message (“The security code doesn’t match. Please check the card.”), that the attempt is logged without the code itself, and that repeated failures trigger your rate limits.
Common mistakes
- Fixed three-digit fields. They lock out American Express customers. Size the field for four digits and validate per brand.
- Converting to an integer.
042becomes42and fails at the issuer. - Optional field without a reason. If you don’t send a code, you lose the issuer’s check entirely.
- Leaking it into logs. The most common way codes end up stored against PCI DSS rules.
- Treating a match as proof of identity. A matching code proves knowledge of the code, not that the payer is the cardholder. Combine it with AVS, 3-D Secure and behavior signals.
Frequently asked questions
Is CVV the same as CVC?
Yes, in practice. CVV2 is Visa’s name and CVC2 is Mastercard’s name for the printed security code. Both are three digits on the back of the card and are checked by the issuer in the same way.
Where is the CID on an American Express card?
On the front, printed above and to the right of the card number. It has four digits, unlike the three-digit codes on the back of most other cards.
Can a website check whether a CVV is correct without the bank?
No. The code is calculated by the issuer with secret keys. A website can only check that it has the right number of digits; correctness is confirmed in the issuer’s authorization response.
Can I store the CVV for recurring payments?
No. The PCI Security Standards Council states that card verification codes are not needed for card-on-file or recurring transactions and must not be stored for those purposes, even if the customer agrees.
Why does my test payment succeed with any CVC?
Most sandboxes accept any code of the right length so you can test the happy path. To simulate a CVC failure, use the gateway’s dedicated test card or trigger value, such as Stripe’s 4000 0000 0000 0127.
Sources
- PCI SSC FAQ — Are merchants allowed to request card verification codes from cardholders?
- PCI SSC FAQ — Can card verification codes be stored for card-on-file or recurring transactions?
- Worldline Direct — CVV (security code names per scheme)
- Sipay Developers — CVV
- Wikipedia — Card security code
- Stripe Docs — Testing (CVC test cards)
Tools used in this guide
Related guides
Written for developers, QA teams and merchants. Generated card numbers are test data: they are not real cards and cannot pay for anything.