< HTTP/1.1 402 Payment Required402 Payment Required
Reserved for future use in digital payment systems. Learn about this experimental status code and modern payment verification alternatives.
- Cacheable
- Only with explicit freshness
- Retry?
- No: payment or plan upgrade required
- Usually sent by
- Origin app (reserved; use is app-specific)
- Spec
- RFC 9110 §15.5.3
- Often confused with
- 403
On this page
- What is 402 Payment Required?
- When Does This Happen?
- Example Responses
- Real-World Example
- 402 vs Other Authorization Codes
- Important Characteristics
- Common Mistakes
- Getting 402 Payment Required right
- Modern Payment Verification Patterns
- Implementation Examples
- Try It Yourself
- Try it with curl
- Related Status Codes
TL;DR: Reserved for future digital payments, rarely used in practice. Most sites use 403 Forbidden with payment info instead.
What is 402 Payment Required?
A 402 Payment Required status code is reserved for future use in digital payment systems. Think of it like a “No Entry Without Ticket” sign—the resource exists, but you need to pay before accessing it. However, this code was never standardized and is rarely used in practice.
While originally intended for digital cash or micropayment systems, modern implementations typically use 401 (Unauthorized) or 403 (Forbidden) with custom payment logic instead.
When Does This Happen?
Although not standardized, you might theoretically see a 402 Payment Required response in:
1. Paywalled Content
Article behind paywall
/premium-article → 402 Payment Required
2. API Rate Limit Exceeded (Paid Tier)
Free tier exhausted, payment required
/api/data → 402 Payment Required → Upgrade to continue
3. Subscription Services
Subscription expired
/members-only-content → 402 Payment Required
4. Metered API Usage
Credits depleted, payment required to continue
/api/translate → 402 Payment Required → Add credits
5. Digital Goods Purchase
Download requires payment
/download/ebook → 402 Payment Required
Example Responses
Paywalled Article:
HTTP/1.1 402 Payment Required
Content-Type: application/json
WWW-Authenticate: Bearer realm="premium-content"
X-Payment-Required: subscription
Link: <https://example.com/subscribe>; rel="payment"
{
"error": "Payment Required",
"message": "This content requires an active subscription",
"subscription_url": "https://example.com/subscribe",
"plans": [
{
"name": "Monthly",
"price": "$9.99/month",
"url": "https://example.com/subscribe/monthly"
},
{
"name": "Annual",
"price": "$99/year",
"url": "https://example.com/subscribe/annual"
}
]
}
API Credit Depletion:
HTTP/1.1 402 Payment Required
Content-Type: application/json
X-RateLimit-Remaining: 0
X-Credits-Required: 100
Retry-After: 3600
{
"error": "Insufficient Credits",
"message": "You have exhausted your API credits",
"credits_required": 100,
"current_balance": 0,
"purchase_url": "https://api.example.com/credits/purchase"
}
Subscription Expired:
HTTP/1.1 402 Payment Required
Content-Type: text/html
X-Subscription-Status: expired
X-Subscription-Expired: 2026-01-01
<!DOCTYPE html>
<html>
<head><title>Subscription Required</title></head>
<body>
<h1>Subscription Expired</h1>
<p>Your subscription expired on January 1, 2026.</p>
<p><a href="/renew">Renew Subscription</a></p>
</body>
</html>
Real-World Example
Imagine you’re trying to access premium API features without sufficient credits:
Client API Request:
GET /api/v1/premium/analytics HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Accept: application/json
402 Payment Required Response:
HTTP/1.1 402 Payment Required
Content-Type: application/json
WWW-Authenticate: Bearer realm="premium-api", error="insufficient_credits"
X-Credits-Required: 500
X-Current-Balance: 0
Link: <https://api.example.com/billing/purchase>; rel="payment"
{
"status": 402,
"error": "Payment Required",
"message": "Insufficient credits for premium analytics endpoint",
"details": {
"credits_required": 500,
"current_balance": 0,
"credits_needed": 500
},
"actions": {
"purchase_credits": {
"url": "https://api.example.com/billing/purchase",
"method": "POST",
"packages": [
{"credits": 1000, "price": "$10.00", "id": "pkg_1k"},
{"credits": 5000, "price": "$40.00", "id": "pkg_5k"},
{"credits": 10000, "price": "$75.00", "id": "pkg_10k"}
]
},
"upgrade_plan": {
"url": "https://api.example.com/billing/upgrade",
"method": "POST",
"plans": [
{"name": "Pro", "monthly_credits": 10000, "price": "$49/month"},
{"name": "Enterprise", "monthly_credits": 100000, "price": "$299/month"}
]
}
}
}
402 vs Other Authorization Codes
| Code | Meaning | Authentication | Payment | Use Case |
|---|---|---|---|---|
| 402 | Payment required | Optional | Required | Digital payments (rare) |
| 401 | Unauthorized | Required | N/A | Missing/invalid credentials |
| 403 | Forbidden | Authenticated | N/A | Insufficient permissions |
| 451 | Legal reasons | N/A | N/A | Censored/blocked content |
Important Characteristics
Reserved Status:
- 402 is officially "Reserved for future use"
- Not standardized in HTTP specification
- No widely accepted implementation
- Most systems use 401 or 403 instead
Modern Alternatives:
# Most common: Use 403 with payment info
HTTP/1.1 403 Forbidden
X-Payment-Required: true
Content-Type: application/json
{
"error": "payment_required",
"payment_url": "/subscribe"
}
Common Mistakes
❌ Using 402 when 401 or 403 is more appropriate
HTTP/1.1 402 Payment Required ← Non-standard, confusing
Location: /subscribe
# Better:
HTTP/1.1 403 Forbidden
X-Reason: subscription_required
Location: /subscribe
❌ Not providing payment information
HTTP/1.1 402 Payment Required ← No info on how to pay
Content-Type: text/plain
Payment required. ← Unhelpful
❌ Using for authentication instead of payment
HTTP/1.1 402 Payment Required ← Wrong code
WWW-Authenticate: Bearer
# Should be:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
✅ If using 402, provide clear payment info
HTTP/1.1 402 Payment Required
Content-Type: application/json
Link: <https://example.com/subscribe>; rel="payment"
{
"error": "payment_required",
"payment_url": "https://example.com/subscribe",
"message": "Subscription required to access this content"
}
Getting 402 Payment Required right
Consider Using 403 Instead:
HTTP/1.1 403 Forbidden
Content-Type: application/json
X-Reason: payment_required
{
"error": "subscription_required",
"message": "Active subscription needed",
"subscribe_url": "/subscribe"
}
If Using 402, Be Descriptive:
HTTP/1.1 402 Payment Required
Content-Type: application/json
Link: <https://api.example.com/pricing>; rel="payment"
{
"error": "Payment Required",
"message": "This API endpoint requires a paid plan",
"current_plan": "free",
"required_plan": "pro",
"upgrade_url": "https://api.example.com/upgrade",
"pricing": {
"pro": "$49/month",
"enterprise": "$299/month"
}
}
Include Clear Call-to-Action:
<!DOCTYPE html>
<html>
<head>
<title>Premium Content</title>
</head>
<body>
<h1>Premium Content</h1>
<p>This article is available to subscribers only.</p>
<a href="/subscribe" class="cta-button">Subscribe Now</a>
<p>Plans starting at $9.99/month</p>
</body>
</html>
Provide Machine-Readable Payment Info:
HTTP/1.1 402 Payment Required
Content-Type: application/json
Link: <https://example.com/api/subscribe>; rel="payment"
{
"error": "payment_required",
"error_description": "Insufficient account balance",
"payment_methods": ["credit_card", "paypal", "stripe"],
"minimum_payment": 10.00,
"currency": "USD",
"payment_endpoint": "/api/payments"
}
Modern Payment Verification Patterns
Subscription Check (Recommended):
app.get('/premium/content', checkSubscription, (req, res) => {
if (!req.user.hasActiveSubscription) {
return res.status(403).json({
error: 'subscription_required',
message: 'Active subscription needed',
subscribe_url: '/subscribe'
})
}
res.json({ content: 'Premium content here' })
})
API Credits System:
app.get('/api/premium-feature', async (req, res) => {
const credits = await getCreditsBalance(req.user.id)
if (credits < REQUIRED_CREDITS) {
return res.status(403).json({
error: 'insufficient_credits',
required: REQUIRED_CREDITS,
current: credits,
purchase_url: '/credits/buy'
})
}
await deductCredits(req.user.id, REQUIRED_CREDITS)
res.json({ data: premiumData })
})
Implementation Examples
Express.js (Using 403 instead):
app.get('/premium/article', authenticateUser, (req, res) => {
if (!req.user.isPremium) {
return res.status(403).header('X-Payment-Required', 'true').json({
error: 'payment_required',
message: 'Premium subscription required',
subscribe_url: '/subscribe',
plans: getPricingPlans()
})
}
res.json({ article: getPremiumArticle() })
})
Django:
from django.http import JsonResponse
def premium_content(request):
if not request.user.has_active_subscription():
return JsonResponse({
'error': 'payment_required',
'message': 'Active subscription required',
'subscribe_url': '/subscribe'
}, status=403) # Using 403, not 402
return JsonResponse({'content': get_premium_content()})
API Gateway Pattern:
// Cloudflare Worker or similar
async function handleRequest(request) {
const apiKey = request.headers.get('X-API-Key')
const usage = await checkUsage(apiKey)
if (usage.credits <= 0) {
return new Response(
JSON.stringify({
error: 'credits_exhausted',
message: 'Please purchase more credits',
purchase_url: 'https://example.com/credits'
}),
{
status: 403, // Using 403 instead of 402
headers: { 'Content-Type': 'application/json' }
}
)
}
return fetch(request)
}
Try It Yourself
Visit our request builder to simulate payment-required scenarios:
- Set method to GET
- Set path to /premium/content
- Try without subscription header
- See 403 response with payment info
- Add subscription header and retry
Try it with curl
402 Payment Required is reserved by RFC 9110 and has no standard behavior, so there is no generic request that triggers it. A few paid APIs return it for exhausted plans or missing payment; the details live in their own docs. To see what one sends, read the headers and body.
curl -i https://api.example.com/v1/premium-endpoint
Related Status Codes
- 401 Unauthorized - Authentication required
- 403 Forbidden - Insufficient permissions (commonly used for payment)
- 429 Too Many Requests - Rate limit exceeded
- 451 Unavailable For Legal Reasons - Legally blocked content
Frequently asked questions
What does 402 Payment Required mean?
A 402 error is reserved for future use in digital payment systems. It was intended to indicate that payment is required to access the resource, but is rarely used in practice.
Why is 402 rarely used?
The HTTP specification reserved 402 for future digital cash systems that never materialized. Most payment systems use 401 or 403 with custom payment flows instead.
When might I see a 402 error?
Some APIs use 402 for subscription limits, usage quotas, or paywall content. Stripe and other payment APIs sometimes return 402 for payment failures.
How should I handle 402 in my application?
Treat it as a payment or subscription issue. Check the response body for details about what payment is required and redirect users to your payment flow.
Sources
Related
418 I'm a Teapot: Origin and Real-World Use
418 I'm a teapot comes from the 1998 April Fools RFC 2324. See why RFC 9110 reserves it, why Node and Go keep it, and why some sites return it to bots.
426 Upgrade Required
The server refuses to perform the request using the current protocol and requires the client to upgrade to a different protocol.
400 Bad Request
400 Bad Request means the server could not parse your request. Find which layer sent it, fix bad JSON and oversized cookies or headers, and reproduce with curl.
HTTP 404 Not Found: What It Means and How to Fix It
404 Not Found means no resource exists at that URL. Find which layer sent it, then fix routing, deploys, rewrites, CDN cache and soft 404s, with curl checks.