After a certain number of sequential requests made in short bursts (normally around 180 requests but I managed to get it down to 50 if the first batch of more than 180 requests succeeds) respecting the API throttle (only 10 concurrent requests with a delay of 1.1 seconds between each batch), the API, seemingly with a random chance, returns an empty response with CORS headers not set resulting, obviously, in a CORS error for the client application.

Here is a screenshot of the error happening after 176 requests:

screenshot of the error happening after 176 requests

And here is one of the errors happening after 50 requests:

screenshot of the error happening after 50 requests

And here is some info about the error response that follows a normal one:

Name Value
Request URL https://api.stackexchange.com/2.3/search?=<query here>
Response headers cache-control: no-cache
content-type: text/html
API key provided? Yes
Free daily quota more than 8500 as per the last successful request

At no point before the error occurs a backoff field is returned but that shouldn't have mattered either way because the code I first reproduced this on was set up to properly handle encountering backoff in a given response. It should also be mentioned that according to the API docs, making less than 30 requests in a second should be fine (however, the reproducing code was specifically designed to only make 10 requests per second):

If a single IP is making more than 30 requests a second, new requests will be dropped.

A very similar set of issues were reported before, and some were even supposed to be fixed:

See this MSO answer of mine for the code that reproduces the error (user id 674039 will result in 191 requests to make) - if it succeeds on the first try, rerun it, and you will likely get the error much earlier (please be weary of your daily API quota if you are a userscript user).

Can this be looked into?

  • 2
    @bad_coder CORS errors have nothing to do with the question :) They are what happens when the response does not contain proper CORS errors which is expected. This question, however, is not about the errors themselves, and all the required information about the response that results in a CORS error I provided separately. The images are only there to illustrate the error happens where I claim it happens. Oct 9, 2021 at 21:30
  • 2
    As far as I recall, this has been happening as long as I've dealt with the SE API. It's just one of the ways the infrastructure deals with you pounding on the API. Design your code to deal with it, and/or reduce the rate at which you make requests to the point where it's very unlikely to happen (there's never a 0% chance, so you need to deal with it). How often this happens depends on the activity level on the server (i.e. stuff you can't know) and how hard you're pounding on the API (how fast you're making requests, how many requests you have in flight at a time, etc.)
    – Makyen
    Oct 9, 2021 at 21:45
  • 2
    "making less than 30 requests in a second should be fine" Ahhh... no. That's not what the docs say. The docs say "we consider > 30 request/sec per IP to be very abusive and thus cut the requests off very harshly." That means that at some points at < 30 requests/s it's merely considered "abusive", rather than "very abusive", and it only cuts off requests "harshly", rather than "very harshly". In other words, 30 requests/s is the absolute hard limit and you almost certainly will be limited to substantially less than that almost all the time.
    – Makyen
    Oct 9, 2021 at 21:51
  • 1
    @Makyen yeah, I realize it is likely related to the rate of making requests to the API regardless of the throttle - however it would be great to hear an official comment regarding what is the expected course of action. I strongly disagree that we, as consumers, should expect for the API to hiccup at any point in time because it breaks the contract promised by the documentation - consumers of a public API should not work around unspecified limitations in my humble opinion. I'd much rather either see a confirmation that this is to be expected (the most disappointing outcome) [1/2] Oct 9, 2021 at 21:53
  • 2
    [2/2] I also understand that "> 30 very harshly" can also mean "< 30 only harshly", however I find it barely acceptable that a third of that number following proper throttling procedures still lands in an abrupt dropping of requests without even a prior backoff being issued once. Not to mention that if this is the worst-case scenario of "yes, this is how it works, deal with it" then the documentation should be clarified to include "however you still may be throttled at an unspecified number of requests". Oct 9, 2021 at 21:57
  • 1
    The docs also say "Note that exactly what response an application gets (in terms of HTTP code, text, and so on) is undefined when subject to this ban". That basically means: if you're sending requests rapidly, we don't guarantee anything when you don't get a valid response from the SE API, so deal with whatever you get, or don't' get. In my experience, the vast majority of non-normal responses are when there's multiple requests in flight, usually later requests get any unusual responses (i.e. the API has decided to block you and just punts).
    – Makyen
    Oct 9, 2021 at 21:57
  • 2
    @Makyen I know about it and read it very differently - it only states that the responses you get when already subject to the throttle will be of undefined nature, which is fine by me (although it is still baffling to see this in a production-grade public-facing API). P.S. I really think that us defending the API for what it does is not a good idea, frankly - it is hardly acceptable even if expected (and I still do not see it as an expected result, unfortunately) Oct 9, 2021 at 22:01
  • I'm not arguing that it can't be or shouldn't be better, or even that I would find it acceptable in something I was designing (unless overridden by business concerns (which seems the case here). I'm merely trying to be clear that it's unlikely to be improved, unless there's something that's clearly changed to being broken. Given that it's unlikely to be improved, it's really just something that you have to program around.
    – Makyen
    Oct 9, 2021 at 22:04
  • @Makyen well, I am still trying despite the chances of the company fixing anything about the API unless it suits the new product (like Collectives triggering v2.3) are understandably very slim :( But I think it is important to report undefined behavior especially when it goes against expectations of an API consumer - "well, this is something to be expected" just does cut it with me. I will, of course, work around it, that's not a big deal at all, but on an off-chance someone out there actually cares... Oct 9, 2021 at 22:09
  • BTW: if you're doing this in a userscript, you can try using either the userscript API to make requests which are not subject to CORS, or install an extension which adds the appropriate CORS headers to requests to the SE API. Personally, I have an extension which adds the CORS headers, which I enable when running into any of the various times when the SE API reverts to using CORS to rate limit, or when it goes a bit wonky.
    – Makyen
    Oct 9, 2021 at 22:32
  • No, no, that was just a sample that is supposed to work from Stack snippets, so no userscript functionality is available :) If I were to make it a userscript, I'd of course consider working around this in the first place or use the GM_*/GM.* API specific functions (that is annoying that one has to resort to that, but it's the reality of things here, I guess), but alas, this is not about making something of mine work but rather about drawing attention to an undefined behavior of the API. Methinks API consumers should expect to get the same response every time they go "by the book". Oct 9, 2021 at 22:40
  • 3
    @Makyen I dropped a thought in the Stack Apps chat maybe we can ponder on that a bit and then go forward from there?
    – rene
    Oct 10, 2021 at 6:55


You must log in to answer this question.

Browse other questions tagged .