All entries
Chapter VIII
Journal · 11 Oct 2026 · 12 min read

3DS2 Frictionless vs Challenge: transStatus Guide

3DS2 results for engineers: every transStatus value, Visa vs Mastercard ECI codes, when liability shifts, and how Stripe, Adyen and Checkout.com report it.

A 3DS2 result of Y does not mean you are protected against fraud chargebacks. The value that decides that is the ECI the card network sends back in the authorisation response, and the network can downgrade it. Stripe only began exposing that response ECI as a separate field on 10 June 2026, so many integrations still store the request ECI and assume liability has shifted when it has not.

This guide covers what happens after authentication. The SCA exemptions guide on this site explains how to ask for a frictionless outcome. This one explains how to read what you get back: every transStatus value, the reason codes worth branching on, Visa and Mastercard ECI codes, and the field names at four PSPs. The pages that rank for these queries today are short reference stubs, and none of them connects status to ECI to liability. That connection is the useful part.

What Is the Difference Between 3DS2 Frictionless and Challenge Flow?

In a frictionless flow, the issuer's Access Control Server (ACS) looks at the data you sent (device fingerprint, billing address, transaction history, amount) and approves authentication without the cardholder doing anything. The cardholder never sees an issuer screen.

In a challenge flow, the ACS decides it needs proof from the cardholder. That can be a one-time passcode, a banking-app approval or biometrics. You render the issuer's UI in an iframe on the web or through the 3DS SDK in an app, and the cardholder completes it there.

The merchant never makes that choice. You can say what you would prefer through threeDSRequestorChallengeInd, but the ACS decides. Your integration has to handle both paths every time, plus a third: decoupled authentication, where the cardholder approves later on another device and you find out asynchronously.

How Does the 3DS2 Message Flow Work?

The protocol has four message pairs. You will see their names in PSP logs.

MessageDirectionWhen
AReq / ARes3DS Server → DS → ACS and backEvery authentication. The ARes either finishes the flow (frictionless) or asks for more.
CReq / CResBrowser or SDK ↔ ACSChallenge only. The cardholder interacts here.
RReq / RResACS → DS → 3DS ServerAfter a challenge or decoupled flow. Carries the final result.
PReq / PRes3DS Server → DSCache refresh of card ranges and 3DS Method URLs.

Before the AReq, browser flows run the 3DS Method: a hidden iframe that lets the ACS fingerprint the device. You report how it went in threeDSCompInd: Y (completed), N (did not complete) or U (no 3DS Method URL for this card range). Cardinal and Nuvei both document a 10-second ceiling, after which you send N and continue. Global Payments recommends closing the iframe after about 3 seconds. Waiting the full 10 seconds is a choice you make at checkout, and it slows every customer for a small gain in frictionless rate.

Three identifiers come back on every transaction: threeDSServerTransID, acsTransID and dsTransID. The dsTransID is the one the scheme knows about and the one you want in dispute evidence.

3DS2 transStatus Values Explained

transStatus is the single-letter outcome. Where it appears tells you as much as its value does.
ValueMeaningAppears inFinal?
YAuthenticatedARes, RReq, final CResYes
NNot authenticated, transaction deniedARes, RReq, final CResYes
UAuthentication could not be performed (technical or other problem)ARes, RReqYes
AAttempt: not authenticated, but proof of attempt generatedARes, RReqYes
RRejected by issuer; do not authoriseARes, RReqYes
CChallenge requiredAResNo
DDecoupled authentication confirmedARes, final CResNo
IInformational only; requestor's challenge preference acknowledgedAResYes
SChallenge using Secure Payment Confirmation (2.3.1+)AResNo
C, D and I were added in 2.2.0. S needs messageVersion 2.3.1 or higher. If SPC cannot run, the issuer falls back to C. EMVCo's whitepaper limits the final CRes to Y, N or D, so a challenge cannot finish with A or U. I is the one that catches people out. It comes back when you sent a data-only or exemption request. The issuer has accepted the information but has not authenticated anyone, so treat it as "no 3DS liability" and not as a soft success.

Which transStatusReason Codes Should You Act On?

transStatusReason is required when transStatus is N, U or R. EMVCo defines codes 01 to 27, reserves 28 to 79 for itself and gives 80 to 99 to each Directory Server. The codes worth branching on:
CodeMeaningWhat to do
01Card authentication failedDo not retry automatically. Ask for another card.
05Expired cardCard update flow
06 / 08Invalid card number / no card recordAsk for the card again
11Suspected fraudHard stop. Feed your fraud model.
13Cardholder not enrolledRetrying will not change it. Decide with your risk team whether to authorise without 3DS.
14Transaction timed out at the ACSOne retry is reasonable
22ACS technical issueOne retry, then fall back
23 / 24Decoupled required but not requested / max time exceededFix your request, or raise threeDSRequestorDecMaxTime
26Attempted but not performed by the cardholderAbandonment. Show the challenge again or offer another method.

The 80 to 99 range is where scheme differences live. In Adyen's spec, 81 means "ACS timed out" on Visa and "challenge exemption accepted" on Mastercard. If you log these codes without the card brand next to them, you cannot interpret them later.

ECI Values for Visa vs Mastercard in 2026

The Electronic Commerce Indicator (ECI) is what the authorisation message carries. Visa and Mastercard use different numbers for the same outcome, which is why mapping ECI by number alone produces wrong answers.

OutcomeVisa (and Amex, Discover, JCB, Diners at Checkout.com)Mastercard
Fully authenticated0502
Attempted0601
Not authenticated / failed0700
Data Only (no authentication)none04

The rows above agree across Stripe and Checkout.com. Beyond them the two PSPs disagree:

  • Mastercard 06. Stripe calls it "merchant-based liability". Checkout.com calls it out of scope or SCA-exempt. Both say no liability shift.
  • Mastercard 07. Stripe says partial shipment or recurring. Checkout.com says a successful recurring transaction secured by 3DS, with liability shift unless it is Apple Pay without a cryptogram.
  • Mastercard 01 and Visa 06. Stripe labels these "attempted". Checkout.com describes them as a stand-in service treating the transaction as successful.
The practical rule is the one Stripe states in its own docs: never read one network's ECI with another network's table. Store the brand next to the ECI. Also store which PSP gave you the label, because the labels differ even where the code does not.

Does 3DS2 Attempted Authentication Shift Liability?

Usually yes, with exclusions. This is where most guides stop too early.

An A result produces Visa ECI 06 or Mastercard ECI 01, and both are generally covered. Braintree's status table backs this up: authenticate_attempt_successful reports liabilityShifted: true. But TabaPay's summary of the Visa rules lists exclusions:

  • Non-reloadable prepaid cards get no attempts protection.
  • If the authorisation goes out without a CAVV, Visa reclassifies the ECI to 07.
  • In the US, merchants in the 3DS Fraud Monitoring Program are excluded, as are MCCs 4829 (money transfer), 5967, 6051 (quasi-cash and crypto), 6540, 7801, 7802 and 7995 (gambling).
For crypto on-ramps and remittance businesses, that last point means an attempted authentication is close to worthless on Visa in the US. It is easy to launch on an attempts-are-fine assumption copied from a general guide and only find out with the first fraud chargebacks under MCC 6051.

Data Only (Mastercard ECI 04, Stripe result data_share_only, Checkout.com exemption data_share) never shifts liability. It exists to give issuers better data for the authorisation decision. In a Stripe Sessions 2026 talk, Stripe said sharing Data Only signals raised conversion by 3.2% on European transactions over €250, but that is a talk figure, not a published dataset.

Stripe vs Adyen vs Checkout.com vs Braintree: Reading the 3DS Result

Each PSP reports the same protocol outcome under different names, and each one hides something different.

StripeAdyenCheckout.comBraintree
Outcomethree_d_secure.resultthreeDS2Result.transStatus3ds.authentication_responsethreeDSecureInfo.status
Raw transStatusNoYesYesOn the nonce only (lookup / authentication)
Reason coderesult_reason (Stripe's own enum)transStatusReasonauthentication_status_reason (only when not Y)Nonce only
Frictionless or challengeauthentication_flowInfer from ChallengeShopper vs IdentifyShopper3ds.challenged (boolean)Infer from lookup.transStatus = C
ECIRequest and response, separatelythreeDS2Result.eci, additionalData.eci3ds.ecieciFlag
LiabilityNot exposedadditionalData.liabilityShiftNot exposed directlyliabilityShifted, liabilityShiftPossible

Stripe's result enum is authenticated, attempt_acknowledged, exempted, failed, not_supported, processing_error and data_share_only. Its result_reason values (abandoned, canceled, rejected, bypassed, protocol_error, card_not_enrolled, network_not_supported) are a Stripe summary. You cannot get EMVCo code 11 from Stripe, so a fraud model that relies on "suspected fraud" from the issuer will not get that signal there.

The detail most teams miss is on the Stripe side. payment_method_details.card.three_d_secure.electronic_commerce_indicator is the ECI from authentication, sent in the request. payment_method_details.card.electronic_commerce_indicator is the network's final value. Stripe's own example shows a Visa payment with result: "authenticated" and request ECI 05 that came back as 07:

"card": {
  "brand": "visa",
  "electronic_commerce_indicator": "07",
  "three_d_secure": {
    "electronic_commerce_indicator": "05",
    "result": "authenticated"
  }
}

That payment has no liability shift. Stripe only populated the response field from 10 June 2026 in the API (22 July in Sigma) and did not backfill it, so dashboards built before then cannot see downgrades.

Checkout.com's async shape also matters for state machines. A 3DS payment returns HTTP 202 with status: "Pending" and _links.redirect.href. A completed payment returns 201. If your client treats any 2xx as captured money, a challenged card will look paid before the cardholder has done anything.

What to Do After U, R or a 3DS Timeout

These are my retry rules:

  • R: do not authorise and do not retry 3DS. The issuer has told you the answer.
  • N with reason 01, 11 or 10: stop and ask for another payment method.
  • U with reason 14 or 22: retry authentication once. If it fails again, decide by risk. Low-value orders can go to authorisation without 3DS and with liability on you. Checkout.com automates this with attempt_n3d and reports it back as 3ds.downgraded: true.
  • U with no reason, or a DS timeout: same as above, but alert when one BIN range starts producing it in volume (my rule of thumb is anything above 1 to 2%). That pattern means an ACS outage, not your bug.
  • Challenge abandoned (reason 26, Stripe abandoned): do not retry silently. Show a clear "your bank needs to confirm this" screen with one retry button.
In the EEA and UK, authorising without 3DS invites a soft decline (Visa 1A, Mastercard 65) on in-scope transactions, which sends you back to 3DS. The card decline codes guide covers that loop.

3DS2 Frictionless Rates in the UK and Europe

Most published rates have no traceable source. The "80 to 85% frictionless" figure that ranks on several vendor blogs cites unnamed "industry benchmarks". The data I could trace comes from Ravelin:

  • In its 2024 data, the UK ranked 22nd of 37 countries for frictionless rate while ranking first for challenge success and overall 3DS success.
  • Its March 2026 report puts UK 3DS success at 95% for 2025, still first. It also says frictionless rates were flat or down in 28 of 37 countries, and links that to issuers turning down more exemption requests.
In short, UK issuers challenge more often, and UK cardholders complete challenges more reliably than anyone else. For a UK merchant, the cost of a challenge is mostly latency and UX, not lost sales.

Opinion: Store the Response ECI and Stop Trusting transStatus

My view is that the response ECI should be the field your systems store as the authentication outcome. transStatus describes what the ACS thought. The response ECI describes what the network accepted, and the network's version is the one that counts in a dispute. I expect most PSPs to follow Stripe in exposing request and response ECI as separate fields within the next year, because merchants fighting fraud disputes need the downgraded value and currently cannot see it.

The draft EMV 3DS v2.4.0 that EMVCo put out for comment in June 2026 (comments closed 1 July) does not change this. Since 2.3.1 in September 2022, EMVCo's changes have focused on Secure Payment Confirmation and out-of-band flows rather than the ECI side.

What This Means for Payments Engineers

1. Persist five fields per authentication: card brand, transStatus, transStatusReason, dsTransID, and the response ECI. On Stripe, read payment_method_details.card.electronic_commerce_indicator, not the one under three_d_secure. 2. Map ECI by brand, never by number. 06 is a liability shift on Visa and none on Mastercard. 3. Treat I and Data Only as unprotected. Keep them out of any "authenticated" metric. 4. Check your MCC before trusting attempts. On Visa in the US, 6051, 4829 and 7995 get no attempts protection. 5. Cap the 3DS Method wait. Measure your frictionless rate at 3, 5 and 10 seconds before keeping the spec maximum. 6. Handle async responses. Checkout.com's 202 Pending, Adyen's ChallengeShopper and decoupled D results all need a pending state that is not "paid". 7. Check you have dropped 2.1.0. Mastercard retired it on 24 September 2024 and Visa on 25 September 2024. Any code path still sending messageVersion: "2.1.0" will be rejected.

Key Takeaways

  • Frictionless vs challenge is the issuer's decision. Your job is to handle Y, N, U, A, R, C, D, I and, from 2.3.1, S.
  • Visa and Mastercard use different ECI numbers: 05/06/07 against 02/01/00, plus Mastercard 04 for Data Only. Stripe and Checkout.com describe Mastercard 06 and 07 differently.
  • Attempted authentication shifts liability on both schemes, except for Visa's prepaid, missing-CAVV and US high-risk MCC exclusions.
  • The response ECI, not transStatus, tells you whether liability shifted. Stripe exposes both. Most PSPs do not.
  • UK issuers challenge more than most, and UK cardholders complete challenges more reliably than anywhere else (95% 3DS success in Ravelin's 2025 data).
I'm Tom Wang, a payments engineer working on card, open banking and stablecoin infrastructure. If your chargeback reason codes show fraud disputes on "authenticated" payments, start by checking the response ECI.