what?
`Last-Modified` / `If-Modified-Since` doesn't match the documented behaviour
There are no plans on updating the current API and it's in maintenance mode. My understanding, is there are plans to redo the API in the future though
There are no plans on updating the current API and it's in maintenance mode. My understanding, is there are plans to redo the API in the future though
Thanks Martin, that's good to know. Thank you and your team for all the good work ![]()
Wow. Nice research. These findings are bugs, it means many of our API calls are unnecessary and causes a higher load on chess.com servers than needed.
Wow. Nice research. These findings are bugs, it means many of our API calls are unnecessary and causes a higher load on chess.com servers than needed.
I started using Etags for the first time only last year and they do save a little time and resources when making multiple requests but I've never used the "If-Modified-Since / Last-Modified" header keys. I'm not sure why I'd ever need those.
But I can see how the purpose of those is completely wasted if false results are being given because of non-standard formats.
Several years ago I remember suggesting in this club that the clubs-matches-endpoint was split into "registration/in_progress" and "finished" because I often need the first set of matches but not the second and given how huge some club archives are that might save a lot of server time.
I was told then it would be forwarded to the developers but nothing came of it and now of course nothing ever will. I think we're stuck with the API as it is?
Wow. Nice research. These findings are bugs, it means many of our API calls are unnecessary and causes a higher load on chess.com servers than needed.
I started using Etags for the first time only last year and they do save a little time and resources when making multiple requests but I've never used the "If-Modified-Since / Last-Modified" header keys. I'm not sure why I'd ever need those.
But I can see how the purpose of those is completely wasted if false results are being given because of non-standard formats.
Several years ago I remember suggesting in this club that the clubs-matches-endpoint was split into "registration/in_progress" and "finished" because I often need the first set of matches but not the second and given how huge some club archives are that might save a lot of server time.
I was told then it would be forwarded to the developers but nothing came of it and now of course nothing ever will. I think we're stuck with the API as it is?
Fortunately when ETag is present, If-Modified-Since/Last-Modified should be ignored.
But we're very much stuck, certainly. To me the biggest flaw is still that players and clubs are identified only by unstable names, not idempotent ids. I have a workaround where I save match refs:
- (club_id, match_id, is_live, is_team_1) for clubs
- (player_id, match_id, is_live, is_team_1, board_index) for players
and tournament refs:
- (player_id, tournament_id, round_1_position) for players
in case of name changes, but they only apply to those who've played matches/tournaments.
Hi,
I would like to report an in consistency regarding
If-Modified-Since/Last-Modifiedbetween the API documentation and the actual behaviour.The API documentation says:
ETag/If-None-Matchworks exactly as documented.If-Modified-Since/Last-Modifieddoes not. Three distinct observations:1. The origin ignores
If-Modified-Sinceregardless of valueProbes below omit
If-None-Matchso only the date header is evaluated (RFC 7232 §6 givesETagprecedence when both are present):Same shape on
/pub/player/{u},/pub/player/{u}/stats,/pub/player/{u}/games/archives, and/pub/match/{id}. For comparison,If-None-Matchwith the same resource returns304with a matching ETag and200with a bogus one — so the conditional-GET path is alive, it just doesn't consultIf-Modified-Since.2. The
Last-Modifiedvalue doesn't track content modificationsnowycatis a closed account so the resource's content is static. The ETagW/"09ef210fc806b620027024c8ed241933"is byte-identical across multiple fetches separated by days. Yet theLast-Modifiedvalue reports a time from earlier this morning.Same shape across a range of historic matches. Fetched a day apart, these ETags are all byte-identical:
These matches are all long-finished (match 12 is from Chess.com's earliest days). The ETag confirms the bodies haven't changed — yet
Last-Modifiedvalues are scattered across the past week, not years ago. Whatever this value is tracking (edge-cache refresh time, perhaps), it isn't origin-resource modification.The upshot: a client that honestly echoed the received timestamp back in
If-Modified-Sincewould get200s forever, because the server's idea of the resource's "modification time" on the next request is going to be later than any value it previously emitted.3. The
Last-Modifiedvalue isn't a valid HTTP-dateA typical response:
RFC 7231 §7.1.1.1 defines exactly three legal HTTP-date forms:
Fri, 17 Apr 2026 11:05:26 GMTFriday, 17-Apr-26 11:05:26 GMTFri Apr 17 11:05:26 2026The value
Friday, 17-Apr-2026 11:05:26 GMT+0000matches none:GMT+0000isn't a legal HTTP-date timezone — RFC 7231 requires the literal stringGMT.Strict RFC 7231 parsers reject it outright (for example Java's
DateTimeFormatter.RFC_1123_DATE_TIMEthrowsDateTimeParseException, and typed-header wrappers built on it silently returnNone). More lenient parsers often parse successfully but drop the timezone — Python'semail.utils.parsedate_to_datetimereturns a naivedatetimefor this input versus a UTC-awaredatetimefor correctly-formed IMF-fixdate, a subtle footgun for code that doesdatetimearithmetic on the result.