HTTP 402: Payment Required
developer.mozilla.org
developer.mozilla.org
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.
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 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.
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.
Also, isn't HTTP 503 just about the same as 500 as far as your garden variety client is concerned--even if it's technically plausible some client, somewhere, might want to more aggressively seek out a stale cached result for a 503?
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Re...
Quite a lot of the web would just ignore the mismatch and serve the resource up anyhow with whatever Content-Type the server wanted, and, honestly, that seems to work OK.
It's not that it may not be an error in some sense, it's that the standard has this rich set of specific errors that seems as if it's coming from some parallel universe where the web evolved much differently. And it's not that there is no overlap with our real universe, it's just that if you read the standard and kind of do a postmodernism-style analysis of what the authors must have thought was important, what you get doesn't much resemble the real-world web of today. Or in the case of HTTP 1.1, even the real world web of the time.
For the developer of the client, there is value in that it tells you to start your troubleshooting by looking at the "Accept" header. By contrast, a generic 400 doesn't give you that hint; maybe there will be something in the response headers or body to give you that hint, maybe there won't be.
That is fairly amusing considering the sort of nonsensical popularity of that phrase (at least in the US).
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".
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.
I wonder how FF/Chrome would react to this!
The fact that "browsers render 404 pages" won't save you when you try to get "clever", err, I mean, "standards compliant" and serve a complicated HTTP page out on 402. It probably won't confuse browsers, which will probably just render the page and leave the user oblivious a 402 occurred, which is precisely why I included "(not browsers, but other ones)".
Browsers are forced to march together in some semblance of lock step. When you step out into the heterogeneous world programming language APIs, "convenience" code written on top of those APIs, frameworks written on top of that convenience code, internal libraries written on top of those frameworks... yeah... you can't get very many complicated semantics through that sort of pipeline. And that's not a terribly unrealistic pipeline, unfortunately.
301 Moved Permanently 302 Found 400 Bad Request 401 Unauthorized 403 Forbidden 404 Not Found 410 Gone 500 Internal Server Error 501 Not Implemented 503 Service Unavailable 550 Permission denied
I wonder if there's even a single client in the world that will get a standards-compliant 412 Precondition Failed and try a second request with a different set of conditions. Or indeed do anything sensibly different at all vs. having received a 404. (I specify "standards-compliant" because I'm sure there's plenty of APIs that use 412 for something non-standard.)
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.
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)
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.
The most annoying part is that this knowledge was abused to make even the most basic and otherwise-useless 404 pages show up in IE.
Back when this was a thing, I literally saw this happen. I have one of these pages saved, which is how I know - it was a page which just had "Not Found - The requested document was not found on this server." on it (along with the site name), and then a long HTML comment saying 'Unfortunately, Microsoft has added a clever new "feature" to Internet Explorer.' and explaining the comment's existence.
All for a 404 page that gave far less useful information than IE's own 404 page did. If the page had any brand styling on it I might understand, but this was literally a bare-bones, no-styling page with nothing useful on it.
Not sure how I’ll find an excuse, but I have years to plan.
406 Unacceptable would have made it more useful for today’s tumultuous world.
User address "123 Main st, Scunthorpe" includes unacceptable language.
One can simply respond with the appropriate redirection code to a login/signup page (or whatever) when the client attempts to access a page where "payment is require" (just like any other authentication/authorization issue).
Getting nothing is adequate when nothing exist. Pretending it was something else is just confusing at best.
I believe the intention of this status code was to allow the application to negotiate payment using some not-yet-invented payment technology.
The browser would presumably shell out to some kind of local wallet or bank website to authorize the payment, all in a split second without the user noticing.
What you're describing is the typical paywall type page where a user is asked for payment.
If you'd like to change the account name, we'd be happy to help with that at hn@ycombinator.com.
https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
I'm not going to count the rest of this post as a guidelines violation because I understand how things like this can drive a person up a wall and we all go on tilt sometimes. But I do want to ask you to make sure not to post like https://news.ycombinator.com/item?id=22082038 and https://news.ycombinator.com/item?id=22068236. Those are the kind of thing we ban accounts for, and I don't want to have to ban you again. Most of your recent comments have been fine for HN.
Oh, I can't tell the truth about what's happening in my state due to OTHER states? Gracias. I didn't even call anyone names. I stated a plain fact and you let butt-hurt people called out on their BS have the advantage.
You are beyond disappointing as a moderator.
> 15. Every Xanadu service provider can charge their users at any rate they choose for the storage, retrieval and publishing of documents.
https://en.wikipedia.org/wiki/Project_Xanadu#Original_17_rul...
But in Shopify’s case, the client has no permissions problem.
What you’re describing really is a 500-range issue ... or even an old fashioned 404.
Like I said on another comment, this really is a header or body issue.
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.
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.
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.
Also, we hope that it will incentivize better content than impression-based payments does
But cash-wise - the pitch is only that our users will bring in more money than ads - if you want to, for example, put premium content behind a paywall, that’s fine, we don’t get involved with that. But, like with advertising, the only real way to increase your payout is to get more unique users.
I’m not sure that our user count is public information right now - but we just came out of private beta last week and it’s growing fast!
Edit: downvotes are funny when I link a 70 upvoted post...
And isn't it obvious it can't satisfy a micropayment niche because ... it's a scam? Any moment the value of it can drop to zero, someone might walk away with the contents of your wallet -- and that someone might be your exchange. All of these had examples.
As opposed to... what?
> someone might walk away with the contents of your wallet
Completely depends on how much you care about securing your wallet. I wouldn't say this is a common occurrence at all.
> and that someone might be your exchange.
An exchange is where you go to trade currencies, why are you keeping your money there? And how is that a problem of the currency?
The issue is that receiving and sending bitcoin payments makes you regulated like a wire transfer service, and the resulting license costs to operate such a business are approximately 1MM USD per US state in which you wish to operate (before you can send a single payment).
It's madness. All of the cool micropayment businesses I want to start are illegal now.
If it makes the payment service provider a wire transfer service then Bitcoin and BTCPayServer already solves this.
Here's a project of mine from a while ago: https://github.com/void4/paymentchannel
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...
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.
This error is fixable by client who has to pay.
Application level data bubbling up to headers is already a major problem. I don’t think one more will hurt.
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...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...
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.> 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?
Not to be "that guy" but HTTP is an application protocol, not a transfer protocol -- this kind of thing definitely wouldn't be appropriate for TCP but it sort of makes sense for the original vision of the web.
>"The parameter to this message gives a specification of charging schemes acceptable. The client may retry the request with a suitable ChargeTo header."
https://www.w3.org/Protocols/HTTP/HTRESP.html
And charge-to is defined as
>"ChargeTo:
>This line if present contains account information for the costs of the application of the method requested. The format is TBS. The format of this field must be in extensible form. The first word starts with a specification of the namespace in which the account is . (This is similar to extensible URL definition.) No namespaces are currently defined. Namespaces will be registered with the registration authority .
>The format of the rest of the line is a function of the charging system, but it is recommended that this include a maximum cost whose payment is authorized by the client for this transaction, and a cost unit."
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.
HTTPPaymentRequired
https://docs.pylonsproject.org/projects/pyramid/en/latest/ap...
LinkPeek is a Pyramid application. I'm streaming live tonight as I read hacker news. Join me here https://www.twitch.tv/fxhp