
HTTP 402: Payment Required - jpomykala
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402
======
krajzeg
I find it interesting that so much of the response here is negative, to the
tune of "This shouldn't have been part of the HTTP protocol, it's useless".

From my point of view, a web where this status code works correctly would be
very different, and mostly in a good way - so I find having this in the
protocol a noble attempt that didn't pan out. But that's not a failure of the
design - the reasons 402 is not able to do anything are more
political/environmental than technical in nature, having more to do with how
the world works, not with how HTTP works.

From the technical point of view, it's very easy to imagine how it could work,
for example: The site says 402, with some standardized headers telling my
browser the amount and purpose. Browser pops up a dialog to let me confirm (if
I want) and choose a payment method from the ones I registered with it. If I
confirm, browser resends the request with a "ChargeTo:
pay://visa.com/<token>". No special interface needed on the website, no need
for me to give credit card info to random websites.

That's a preferable outcome to what we have now. Sure, it didn't end up
working that way. But: a) it's hard to predict what'll get traction at the
time of protocol design, b) it's never too late for somebody to salvage this
status code, like the REST revival did with so many other HTTP status codes
that were rarely used.

~~~
StavrosK
The W3C Web Payments standard is more or less what you describe.

------
timzaman
This is actually used. I get it all the time.

The only thing very interesting about 402 is that it is so close to 400 -
meaning some committee must have thought this would be important for the
future (of the internet). I guess history didn't pan out this way.

On GCP: [https://cloud.google.com/resource-
manager/docs/core_errors](https://cloud.google.com/resource-
manager/docs/core_errors) PAYMENT_REQUIRED (402) dailyLimitExceeded402: A
daily budget limit set by the developer has been reached. quotaExceeded402:
The requested operation requires more resources than the quota allows. Payment
is required to complete the operation. user402: The requested operation
requires some kind of payment from the authenticated user.

~~~
jerf
"meaning some committee must have thought this would be important for the
future (of the internet)."

Have a read down the entire standard [1] with an eye to that. There's a number
of codes that are useless (some deprecated), and a number of other codes that
I feel uncomfortable calling _useless_ , but compared to how the web evolved,
certainly aren't working the way the initial designers intended. 406 "Not
Acceptable", for instance, is for when the client sent up Accept-* headers
that don't match anything the server offers. That's technically usable, but
content negotiation ultimately didn't play as big a part of the web as RFC
7231's text suggests the authors thought it would.

There's a lot of response codes squeezed on both sides by the fact that 1.
they're too underspecified to be really useful (yes, it's great that you can
return 402 payment required, but where is the browser supposed to go from
there?) and 2. had they been specified enough to use at the time they were
specified, they would have been utterly wrong. I don't think there's any way
to square that circle at a standards level.

[1]:
[https://tools.ietf.org/html/rfc7231#section-6.2](https://tools.ietf.org/html/rfc7231#section-6.2)

~~~
jlokier
> it's great that you can return 402 payment required, but where is the
> browser supposed to go from there?

Don't forget the browser is allowed to return a HTML page with the 402 error,
telling the browser, user, or other user-agent exactly what to do.

For example the 402 error page could contain a payment form to be filled in,
or other instructions to the user.

Or even a button: "Yes I agree to pay $10 to see the article".

~~~
jerf
The entire point of returning a status code, at least in theory, would be to
_not_ simply be practically-semantically indistinguishable from a 200.

In practice, if you try to return a 402 with an HTML page explaining how to
pay, you'll quickly revert that because you'll break some percentage of HTTP
clients (not browsers, but other ones) that will try to do "something" with
402, even if it's just assuming "well, it's a 4xx so it's basically a 404",
and you'll return a 200 for that page. On the one hand, it isn't necessarily
that many clients that will blow up, but on the other hand, you'll observe
that _no_ clients will be confused by the 200, so the engineering pressures
are pretty consistent here, which is why everybody ends up in the same place.

In theory, if you read the standard, you ought to be able to return a 402, and
use content-negotiation to decide whether to return it in a human-readable
format, or some rich selection of machine-readable formats, and you ought to
be able to annotate it with several dimensions of somewhat overlapping
information about exactly how to cache it and exactly what conditions should
cause the cache to be expired, including some specification of the HTTP-
standard authorization techniques available, etc. etc.... in practice, pretty
much every individual element in that collection only sorta works, and trying
to do all of them at once essentially impossible at scale, and you'll return a
200 page with HTML and expect the client to pick up the pieces, and if you do
offer a JSON view, while you may honor the negotiation stuff you'll probably
also allow a querystring or form parameter to ask for JSON too because you
can't count on the people writing clients to even know what headers are....
and libraries often make them somewhat less convenient to work with than form
parameters, since everybody needs those. And you probably won't "content
negotiate" at all, but just have entirely separate URLs for your human stuff
and your official "REST API", because most people who try to get clever and
make your human website URLs also be the "REST API" pretty quickly discover
it's not worth the effort.

~~~
JohnBooty
I'm sorry, but this is a misunderstanding of the web at a very basic level.

    
    
        In theory, if you read the standard, you ought 
        to be able to return a 402 [snip]
    

Every "problem" you just described applies to 404 as well, and everything
handles that just fine.

There is absolutely no problem with servers returning 4xx/5xx codes along with
some HTML to render.

All the other things you just described, the content negotiation and so on,
are highly debatable at best but the important thing to understand is that
they're completely orthogonal to whether or not the server has returned some
HTML along with the error code.

You _are_ correct in that human readers don't really know/care whether it's a
4xx/5xx code. But that's fine. They're humans, so it's OK for the HTML
returned to give them a choice of what to do.

Non-200 response codes are, of course, already massively useful for other bits
of code, for RESTful services and otherwise.

~~~
toast0
> Every "problem" you just described applies to 404 as well, and everything
> handles that just fine.

I'm not sure what value of everything you're using, but I remember Internet
Explorer's 'friendly error messages'. If your html isn't long enough, and that
abomination still exists, you'll get Microsoft's 404 instead of your nice and
short 404.

I have worked with many embedded http clients that can't reliable return
content unless it's from an HTTP 200. I wouldn't write one like that, but you
don't always get to pick your platform, and some platforms give you HTTP or
nothing, so you can't use TCP and do a better job (or more often, you have
much more important platform issues to work around than to roll your own http
when the platform one works enough and it's trivial to just return 200 in case
the server had something to return to the client)

~~~
heavenlyblue
Also many libraries are built by throwing exceptions for non-200 error codes.

~~~
JohnBooty
No conflict there.

For SOAP stuff, an exception on 4xx/5xx is generally a sensible design.

For human user-agents (ie, web browsers) there's still no conflict. Deciding
whether or not to render some HTML is orthogonal to whether or not some other
action might be taken. Generally, you do want to present a choice to the user
at this point.

------
jto1218
Shopify’s REST API returns 402s when the shop whose data you’re interacting
with hasn’t paid its Shopify bill. Always thought it was an interesting usage
cause the payment-required relationship is between the shop and Shopify, as
opposed to the shop and the application hitting the API.

~~~
OJFord
Actually I'm not sure that is interesting - from Shopify's perspective it _is_
payment-required. If the shop's dodgy JS sent a malformed request body, you'd
get a 400 - even though the bad-request relationship is between the shop and
Shopify.

~~~
kedean
It does violate the contract of 4xx errors though, that a 4xx indicates a
client error. If the store hasn't paid up, that's not the clients fault nor
can they fix it. It should be some kind of 5xx for customers.

~~~
krainboltgreene
If an admin disables your account by accident, that's still a 401. Just
because the client can't change something, doesn't mean it doesn't fit along
with the 4XX brand.

~~~
takeda
401 means authentication is required. If Shopify is sending that to clients,
because admin disabled access, that's just another example of abusing the
error codes

------
jedberg
At Reddit if there was a bot that was hammering us too hard, I’d reconfigure
the load balancer to return a 402.

Sometimes the bot would stop after the first request. I’d always wondered if
it was because it stopped after a 4xx response or if I was crashing the bot.

------
mikro2nd
I think this actually amounts to a mistake in the protocol design: It should
not be a 4xx status code at all.

From the current list of status codes[0]:

    
    
        3xx: Redirection - Further action must be taken in order to complete the request
        4xx: Client Error - The request contains bad syntax or cannot be fulfilled
    

"402 Payment required" is _not_ a client _error_ (though it is possibly a
reflection of client state). The appropriate status indication should be a 3xx
status, say "306 Payment required".

Bad design choice as it currently stands.

[0] [https://www.iana.org/assignments/http-status-codes/http-
stat...](https://www.iana.org/assignments/http-status-codes/http-status-
codes.xhtml)

~~~
aww_dang
401 and 403 are authentication related, so it fits in well.

~~~
mikro2nd
You're absolutely right. So by the same logic I'll argue that those should
_also_ be 3xx codes and not 4xx. After all, being "unauthorized"/"forbidden"
is a valid state for a client to be in (so not an error!) albeit one that
might not be fixable by the client, whereas "payment required" seems to imply
that the client _can_ fix the condition.

~~~
aww_dang
401 is used for logins in the proper case. In practice 403 is used here too.
The example of HTTP authentication requires a follow up request to be made.
This would be unresolvable if the user doesn't have an account or couldn't
sign up.

403 would be used anytime the user doesn't have permission. This could be an
authenticated user who simply does not have permission to access the requested
resource.

Unlike 3xx these states require user intervention. If you trust your browser
to save passwords, perhaps not. Similarly for a 402, a payment flow would be
required before the request could be completed.

Again, you might choose to trust a resource that prompts you with a 402, but
that would be like automatically sending your password.

Usually when building a webapp, your 401 error page will contain a
login/signup form, or you can use the HTTP authentication scheme. There's no
need to redirect, because your 401 contains the information needed for the
user.

3xx on the other hand is usually handled by the client, but I may be mistaken.
Take care.

------
yuvalkarmi
Didn’t Tim Berners-Lee originally envision a way to pay for individual World
Wide Web content via micro-payments? This would have been perfect for that.
While most content today is monetized via advertisements (which ultimately
directs which content gets published to maximize views), I’m guessing this was
originally meant to enable the sort of transactional content delivery
originally envisioned at the onset the web.

I know there have been multiple experiments with content micropayments (I
remember google had a product that was meant to allow you to charge up a
wallet and use it to avoid displaying ads on participating news publications),
and I vaguely remember reading something about Brave doing something similar.
Really curious if this would go anywhere in this context.

~~~
snazz
I think this idea is really only viable now that we have cryptocurrencies--
just to keep your payment information out of the wrong hands. That said, the
popularity of adblockers has forced website owners to rely more on affiliate
links and sponsorships instead of ads in the traditional sense.

~~~
jrockway
I think websites are still using ads.

The problem with micropayments is that people get sticker shock. You put $10
in your micropayment account, browse around, and that money is gone whereas
your friends that just look at ads and ignore them still have $10. (This was
my impression, anyway, from when Google was testing that "pay to disable ads"
service.) This means that publishers are forced to lower the price of an
impression, and of course then advertisers ask to pay less. Guess who loses
out? Publishers and the ad networks. Guess who would be well-placed to
encourage the adoption of micropayments? Publishers and the ad networks.
That's why we don't have micropayments. Getting money from consumers is an
exercise in frustration and a race to the bottom. Getting money from
businesses is an exercise in "add an extra 0 to the price and see if they
still buy".

Having said that, micropayments seem to be working fine on platforms like
Twitch.

~~~
jes5199
I’m going to break character and talk about my work - I’m at a company,
Scroll.com , that sorta does micropayments - but instead of having an account
that you drain as you browse, we have a flat monthly subscription that we
divide up among the sites in our network. Payout is based on the ratios of how
much time you spent on each site. So if you read a lot or a little it’s the
same, from your point of view. And generally it still delivers more $ per
impression than advertising would.

Also, we hope that it will incentivize better content than impression-based
payments does

~~~
smichel17
Isn't that what flattr did?

~~~
jes5199
there are a few competitors in this space, yes. We also get compared to
Brave’s attention coin system. We’re differentiated in that we parter with
major news-media sites - newspapers and magazines, mostly, so far.

------
herpderperator
I would say this is too high level for the HTTP protocol. It sounds like an
application-level check. If we had application-level error codes bubble up to
the HTTP layer like this, we would have trouble keeping up with them all.

~~~
hunter2_
I'm on the fence about whether this is pedantic, but in the OSI model, this
absolutely is the application level.

~~~
herpderperator
I was not strictly referencing the OSI model here, despite using terminology
that conflates it. In my comment, I am using "application" to refer to the
thing that the HTTP protocol is transporting. Example: Making a payment with
the PayPal API. PayPal is the application, interfaced with HTTP. If I want to
return an error code that an account was banned, I am arguing we should not be
returning esoteric HTTP error codes but stick to basic ones and send the
PayPal-specific error codes as payload.

Here's a real-world example with Linux.

    
    
      eclipse ~ # route add 29834
      SIOCADDRT: No such device
    

"No such device" is -ENODEV. Here's a list of all of them: [https://www-
numi.fnal.gov/offline_software/srt_public_contex...](https://www-
numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html)

In the above example, the developer is trying to retrofit one of Linux's
standard error messages to one that best fits the condition this application
has encountered. Do you think that error message makes any sense to the user?
I don't.

Let's try another one:

    
    
      eclipse ~ # route del 1234
      SIOCDELRT: No such process
    

Choosing to use Linux's errno.h here instead of a custom message is kind of
like choosing to use using HTTP's status codes to get your application's
problem explained to the user, even though there might not be an HTTP-level
code that specifically fits the problem description. Maybe 402 Payment
Required works for payments, but what about something else? What if you need
to first do action x before doing action y, should we have HTTP error 469
DoXBeforeY? That's what I was trying to explain.

Wikipedia's page on the OSI model references this as "application-entity" and
"application":

When identifying communication partners, the application layer determines the
identity and availability of communication partners for an application with
data to transmit. The most important distinction in the application layer is
the distinction between the application-entity and the application. For
example, a reservation website might have two application-entities: one using
HTTP to communicate with its users, and one for a remote database protocol to
record reservations. Neither of these protocols have anything to do with
reservations. That logic is in the application itself. The application layer
has no means to determine the availability of resources in the network. [0]

[0]
[https://en.wikipedia.org/wiki/OSI_model#Layer_7:_Application...](https://en.wikipedia.org/wiki/OSI_model#Layer_7:_Application_Layer)

~~~
hunter2_
Maybe a casual user doesn't care, but a power user / dev trying to script it
would benefit. Just like how some users of Linux applications just use them
interactively and read the English language stderr stream, while others
appreciate a myriad of exit codes so a calling script can unambiguously do
different things depending on what sort of problem the application is
presenting.

~~~
herpderperator
Well, the exit codes of both of those commands (despite being different) is
actually 7. But 7 does not match either error string, so the power user would
have to string search it anyway.

    
    
      eclipse ~ # route add 1234
      SIOCADDRT: No such device
      eclipse ~ # echo $?
      7
    
      eclipse ~ # route del 1234
      SIOCDELRT: No such process
      eclipse ~ # echo $?
      7
    

Maybe I used a bad example? I get your point though.

------
dang
A thread from 2014:
[https://news.ycombinator.com/item?id=7857236](https://news.ycombinator.com/item?id=7857236)

------
zelly
Nowadays most news websites send this as a "200".

~~~
taywrobel
200, including partial content, and still with adds.

~~~
quickthrower2
200 with full content for robots

------
ricardobeat
The RFC offers no reasoning for this besides

> The 402 (Payment Required) status code is reserved for future use.

Isn't this obviously domain-specific and something that should not be part of
the transfer protocol?

~~~
westurner
> _The new W3C Payment Request API [4] makes it easy for browsers to offer a
> standard (and probably(?) already accessible) interface for the payment data
> entry screen, at least._ [https://www.w3.org/TR/payment-
> request/](https://www.w3.org/TR/payment-request/)

~~~
djur
The Payment Request API doesn't use 402 Payment Required, does it?

~~~
westurner
It really could

------
Lammy
Packix.com uses this for paid iOS jailbreak tweaks/themes! This is what I get
if I try to install a tweak that I haven't paid for:
[https://i.imgur.com/RpomgNa.jpg](https://i.imgur.com/RpomgNa.jpg)

------
epicgiga
Would be nice if all those news sites with "you've read n articles, subscribe
to read more" popups could return 402. Then I could have my browser
automatically disable js for them and reload.

------
RL_Quine
Problem is, things like this will never be used. Everybody wants to have their
own application chrome, so these sort of features end up buried and forgotten.

~~~
taneq
Every page having its own payment system is a bug, not a feature. It relies on
every vendor to independently implement secure payments and it trains users to
type their credit card number into any old web site.

~~~
quickthrower2
What’s the one payment system we should use for all payments in any country
for every website?

~~~
wyager
This is a plausible use case for Bitcoin (over the Lightning network). Works
in any country, and could be used by any website.

~~~
RL_Quine
The only people really promoting Lightning are those who haven't used it.

------
mankins
We built the Condé Nast paywalls (New Yorker/Wired/Vanity Fair) using the 402
status code. A 402 indicates to the browser that no acceptable payment method
was negotiated and the content returned is not the full url requested.

We imagine clients sending an "Accept-Payment" header just as they send an
"Accept" or "Accept-Language" header today. When the server is unable to
satisfy their request, it returns a 402 indicating that no acceptable payment
method was found.

It's true that browsers may not be currently sending these Accept-Payment
headers; we auto-create the headers at the edge based on other headers
(cookies). Conceptually this simplifies our stack and gives us a way that we
might be able to have more of a "conversation" between web users and the site
about how they want to monetize our content.

For instance a user may have ad-block enabled so why not tell the server that
("Accept-Payment: ads;q=0") and we'll serve the page based on this
information.

I envision a future where the web browser may have multiple payment methods
built into it (micro-payments, subscriptions, ads, etc.) and a "conversation"
happens between the client and server to figure out what the "best" way
forward is for both parties. We don't need new headers or methods for this, we
simply need to re-use existing status codes and headers.

~~~
sterlind
The full page distinction is very useful and nuanced. You're returning partial
content, so it's not a regular 4xx, but readers can't go past the fold, so
it's not a 2xx. It's a good niche for the status code. I hope these headers
catch on.. payment vs. content negotiation seems a natural fit.

------
vortico
The difficulty of micropayments in my experience is 1) payment processing and
2) taxes. Our payment systems and laws just aren't set up to make this
feasible. I think it would actually be common and well-accepted if these
obstacles magically we're removed.

~~~
aww_dang
Nanocurrency addresses the payment processing end. Instant, feeless and
decentralized transactions.

[https://nano.org](https://nano.org)
[https://nanolinks.info/#games](https://nanolinks.info/#games)

~~~
vortico
The difficulty in this case is that the user must use this service. Most users
want to use credit card or PayPal.

------
squarefoot
I wish I and other colleagues had shirts showing this error back then, when
working at a place without seeing a dime for the first 3 months.

------
LAMike
Lightning Network will make use of this code during this decade

------
buboard
Brave browser should implement this. Or metamask

~~~
PhilippGille
Here's the GitHub issue with the discussion for Joule (similar to Metamask but
for Bitcoin's Lightning Network): [https://github.com/joule-labs/joule-
extension/issues/46](https://github.com/joule-labs/joule-extension/issues/46)

------
wessorh
Just changed all my 404 error pages to 402

~~~
jacurtis
402 makes sense. "Theres no page here but I can make a page here if you pay
me."

------
PhilippGille
I use this status code in my Go middleware for true pay-per-call APIs (payable
via Bitcoin's Lightning Network) and my demo deployment:

\- [https://github.com/philippgille/ln-
paywall](https://github.com/philippgille/ln-paywall)

\- [https://lightning.ws](https://lightning.ws)

------
wired_devil
It is easier for the frontend developer to look only to the status code of the
response and pop up a paywall or something, rather than some message in the
boby. The same goes for 401 Unauthorized or 403 Forbidden, etc.

------
samantohermes
Late stage corporativism...

------
samename
402 is the area code in Eastern Nebraska (think Omaha and Lincoln)

------
mortdeus
This is the moral equivalent of a white flag in the sense that were surrending
the idea of free global internet. We shouldn't own the air bro. (You know
after we've managed to snip in half all the wires).

~~~
wyager
You already pay to use the internet. You just do it in underhanded inefficient
ways like giving advertising companies access to your brain.

------
foxhop
In 2011 I launched my bootstrapped startup "LinkPeek"
([https://linkpeek.com](https://linkpeek.com)) and I used the error code 402
when a customer's account was delinquent.

HTTPPaymentRequired

[https://docs.pylonsproject.org/projects/pyramid/en/latest/ap...](https://docs.pylonsproject.org/projects/pyramid/en/latest/api/httpexceptions.html)

LinkPeek is a Pyramid application. I'm streaming live tonight as I read hacker
news. Join me here [https://www.twitch.tv/fxhp](https://www.twitch.tv/fxhp)

~~~
dang
That is strangely interesting.

