Could well be the use of the important status_code option, which is a reply header:
status_code(-Code)
If this option is present and Code unifies with the HTTP status code, do not translate errors (4xx, 5xx) into an exception. Instead, http_open/3 behaves as if 2xx (success) is returned, providing the application to read the error document from the returned stream.
Headers is a list, so you pass [[opt(val), ...]] rather than [opt(val), ...]
It should not. It merely makes header fields of the reply accessible. Note that the docs say this is a backward compatibility option. Note that the option values should be unbound.
If weird things happen, use
?- debug(http(_)).
before http_get/3. That will print details on the request sent and response received. Note that recent versions have the libraries compiled in optimised mode, disabling debug/3 statements. To use them anyway, use