doi.org *sometimes* redirects to api.crossref.org which fails with HTTP 404/406
I tried to add 10.1109/AFIPS.1966.58 using "Add by ID" in Zotero 7.0.27 (64-bit). It fails with the error message: "Zotero could not find a record for the specified identifier. Please verify the identifier and try again."
Debugging this with the Browser Console (using menu item Tools -> Developer -> Error Console), I see that Zotero fetches . That succeeds and returns a 302 redirect to the location .
So, Zotero then tries to download that, as of course it would be expected to do. But that fetch fails, with HTTP "404 Not Found". When this happens the request headers are:
GET /v1/works/10.1109%2FAFIPS.1966.58/transform HTTP/2
Host: api.crossref.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: application/vnd.datacite.datacite+json, application/vnd.crossref.unixref+xml, application/vnd.citationstyles.csl+json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
TE: trailers
and the response headers are:
HTTP/2 404 Not Found
date: Sat, 01 Nov 2025 08:43:57 GMT
content-type: application/vnd.crossref.unixref+xml;charset=UTF-8
vary: Accept
access-control-expose-headers: Link
access-control-allow-headers: X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, Accept-Ranges, Cache-Control
access-control-allow-origin: *
server: Jetty(9.4.40.v20210413)
x-rate-limit-limit: 50
x-rate-limit-interval: 1s
x-api-pool: public
permissions-policy: interest-cohort=()
X-Firefox-Spdy: h2
That was quite confusing, I don't know why that would happen. But I get the same result if I try to fetch that result in my actual browser, by hand. So the problem is not isolated to Zotero. Indeed, if I try to fetch the URL with curl it still fails (though slightly differently):
$ curl -v -i -A '' 'https://api.crossref.org/v1/works/10.1109/AFIPS.1966.58/transform'; echo
* Trying 98.83.103.139:443...
* Connected to api.crossref.org (98.83.103.139) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: CN=*.crossref.org
* start date: Dec 31 00:00:00 2024 GMT
* expire date: Jan 29 23:59:59 2026 GMT
* subjectAltName: host "api.crossref.org" matched cert's "*.crossref.org"
* issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M02
* SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /v1/works/10.1109/AFIPS.1966.58/transform]
* h2h3 [:scheme: https]
* h2h3 [:authority: api.crossref.org]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x5585646a6610)
> GET /v1/works/10.1109/AFIPS.1966.58/transform HTTP/2
> Host: api.crossref.org
> accept: */*
>
< HTTP/2 406
HTTP/2 406
< date: Sat, 01 Nov 2025 09:13:04 GMT
date: Sat, 01 Nov 2025 09:13:04 GMT
< content-type: text/plain;charset=utf-8
content-type: text/plain;charset=utf-8
< access-control-expose-headers: Link
access-control-expose-headers: Link
< access-control-allow-headers: X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, Accept-Ranges, Cache-Control
access-control-allow-headers: X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, Accept-Ranges, Cache-Control
< access-control-allow-origin: *
access-control-allow-origin: *
< server: Jetty(9.4.40.v20210413)
server: Jetty(9.4.40.v20210413)
< x-rate-limit-limit: 50
x-rate-limit-limit: 50
< x-rate-limit-interval: 1s
x-rate-limit-interval: 1s
< x-api-pool: public
x-api-pool: public
< permissions-policy: interest-cohort=()
permissions-policy: interest-cohort=()
<
* Connection #0 to host api.crossref.org left intact
No acceptable resource available.
So, I'm not sure which of the two web sites is doing something unexpected. Should doi.org be issuing a redirect to a different location? Or, should api.crossref.org be returning a different response for that URL?
Is there anything I can change on my end to get this to work?
I notice for example that other AFIPS DOI values behave differently. For example returns a redirect to and that seems to work just fine.
However, trying the same thing again a few minutes later, I see that when I fetrch with curl it returns a redirect to which seems to work. Similarly fetching the doi.org URL manually. Though Zotero is still exhibiting the failure (perhaps because it is fetching URLs through a re-used HTTP connection, making the problem behaviour sticky).
Debugging this with the Browser Console (using menu item Tools -> Developer -> Error Console), I see that Zotero fetches . That succeeds and returns a 302 redirect to the location .
So, Zotero then tries to download that, as of course it would be expected to do. But that fetch fails, with HTTP "404 Not Found". When this happens the request headers are:
GET /v1/works/10.1109%2FAFIPS.1966.58/transform HTTP/2
Host: api.crossref.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: application/vnd.datacite.datacite+json, application/vnd.crossref.unixref+xml, application/vnd.citationstyles.csl+json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
TE: trailers
and the response headers are:
HTTP/2 404 Not Found
date: Sat, 01 Nov 2025 08:43:57 GMT
content-type: application/vnd.crossref.unixref+xml;charset=UTF-8
vary: Accept
access-control-expose-headers: Link
access-control-allow-headers: X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, Accept-Ranges, Cache-Control
access-control-allow-origin: *
server: Jetty(9.4.40.v20210413)
x-rate-limit-limit: 50
x-rate-limit-interval: 1s
x-api-pool: public
permissions-policy: interest-cohort=()
X-Firefox-Spdy: h2
That was quite confusing, I don't know why that would happen. But I get the same result if I try to fetch that result in my actual browser, by hand. So the problem is not isolated to Zotero. Indeed, if I try to fetch the URL with curl it still fails (though slightly differently):
$ curl -v -i -A '' 'https://api.crossref.org/v1/works/10.1109/AFIPS.1966.58/transform'; echo
* Trying 98.83.103.139:443...
* Connected to api.crossref.org (98.83.103.139) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: CN=*.crossref.org
* start date: Dec 31 00:00:00 2024 GMT
* expire date: Jan 29 23:59:59 2026 GMT
* subjectAltName: host "api.crossref.org" matched cert's "*.crossref.org"
* issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M02
* SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /v1/works/10.1109/AFIPS.1966.58/transform]
* h2h3 [:scheme: https]
* h2h3 [:authority: api.crossref.org]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x5585646a6610)
> GET /v1/works/10.1109/AFIPS.1966.58/transform HTTP/2
> Host: api.crossref.org
> accept: */*
>
< HTTP/2 406
HTTP/2 406
< date: Sat, 01 Nov 2025 09:13:04 GMT
date: Sat, 01 Nov 2025 09:13:04 GMT
< content-type: text/plain;charset=utf-8
content-type: text/plain;charset=utf-8
< access-control-expose-headers: Link
access-control-expose-headers: Link
< access-control-allow-headers: X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, Accept-Ranges, Cache-Control
access-control-allow-headers: X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, Accept-Ranges, Cache-Control
< access-control-allow-origin: *
access-control-allow-origin: *
< server: Jetty(9.4.40.v20210413)
server: Jetty(9.4.40.v20210413)
< x-rate-limit-limit: 50
x-rate-limit-limit: 50
< x-rate-limit-interval: 1s
x-rate-limit-interval: 1s
< x-api-pool: public
x-api-pool: public
< permissions-policy: interest-cohort=()
permissions-policy: interest-cohort=()
<
* Connection #0 to host api.crossref.org left intact
No acceptable resource available.
So, I'm not sure which of the two web sites is doing something unexpected. Should doi.org be issuing a redirect to a different location? Or, should api.crossref.org be returning a different response for that URL?
Is there anything I can change on my end to get this to work?
I notice for example that other AFIPS DOI values behave differently. For example returns a redirect to and that seems to work just fine.
However, trying the same thing again a few minutes later, I see that when I fetrch with curl it returns a redirect to which seems to work. Similarly fetching the doi.org URL manually. Though Zotero is still exhibiting the failure (perhaps because it is fetching URLs through a re-used HTTP connection, making the problem behaviour sticky).
Upgrade Storage
or the GET request https://api.crossref.org/v1/works/10.1109/AFIPS.1966.58 (which returns the 406 Resource not found that you see above).
That's all that's relevant for the inability of Zotero (or any other tool) to get metadata for that DOI. You can report this to the publisher, who can fix their registration.
The redirect from doi.org to CrossRef you're seeing is expected. Zotero Add by Identifier uses content negotiation, which makes a request to doi.org which then gets redirected to the appropriate DOI registration authority.