- Home
- HTTP Status Codes
- 402 Payment Required
Status Code
402 Payment Required
Reserved for future use in digital payment systems. Learn about this experimental status code and modern payment verification alternatives.
What is 402 Payment Required?
TL;DR: Reserved for future digital payments, rarely used in practice. Most sites use 403 Forbidden with payment info instead.
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"
}
]
}
```text
**API Credit Depletion:**
```http
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>
```text
## Real-World Example
Imagine you're trying to access premium API features without sufficient credits:
**Client API Request:**
```http
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"}
]
}
}
}
```text
## 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:**
```text
- 402 is officially "Reserved for future use"
- Not standardized in HTTP specification
- No widely accepted implementation
- Most systems use 401 or 403 instead
```text
**Modern Alternatives:**
```http
# 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
```text
**❌ Not providing payment information**
```http
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
```text
**✅ If using 402, provide clear payment info**
```http
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"
}
Best Practices
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"
}
```text
**If Using 402, Be Descriptive:**
```http
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>
```text
**Provide Machine-Readable Payment Info:**
```http
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' })
})
```javascript
**API Credits System:**
```javascript
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() })
})
```javascript
**Django:**
```python
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
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.