yyyyyyyan / bandcamper

Bandcamp downloader
MIT License
44 stars 9 forks source link

403 Forbidden #22

Open OpGWjzFVI opened 4 weeks ago

OpGWjzFVI commented 4 weeks ago
⟩ bandcamper --verbose --destination ~/Music/Staging/ https://mutablemusic.bandcamp.com/album/hyperrealism

[?] Searching available downloads for URL https://mutablemusic.bandcamp.com/album/hyperrealism

[!] Request error (403) when getting music data from https://mutablemusic.bandcamp.com/album/hyperrealism
auralius-dev commented 2 weeks ago

This is an awesome tool, but it seems like bandcamp's varnish cache is returning 403, with cache error 54113.

(.py-venv) > bandcamper -f flac --fallback -o "{artist}/{album}/{track_num:02d} {artist} - {track}.{ext}" https://alonmormusic.bandcamp.com/
Traceback (most recent call last):
  File "/home/user/.py-venv/bin/bandcamper", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/user/.py-venv/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.py-venv/lib/python3.12/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/user/.py-venv/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.py-venv/lib/python3.12/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.py-venv/lib/python3.12/site-packages/bandcamper/__main__.py", line 172, in main
    bandcamp_downloader.add_url(url)
  File "/home/user/.py-venv/lib/python3.12/site-packages/bandcamper/bandcamper.py", line 127, in add_url
    self._add_urls_from_artist(url)
  File "/home/user/.py-venv/lib/python3.12/site-packages/bandcamper/bandcamper.py", line 86, in _add_urls_from_artist
    response = self.requester.get_request_or_error(source_url)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.py-venv/lib/python3.12/site-packages/bandcamper/requests/requester.py", line 29, in get_request_or_error
    return self._request_or_error("GET", url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.py-venv/lib/python3.12/site-packages/bandcamper/requests/requester.py", line 25, in _request_or_error
    response.raise_for_status()
  File "/home/user/.py-venv/lib/python3.12/site-packages/requests/models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://alonmormusic.bandcamp.com/music

With one of the example commands,

(.py-venv) > bandcamper -f flac "https://stippling.bandcamp.com/album/perfect-life"

[?] Searching available downloads for URL https://stippling.bandcamp.com/album/perfect-life
[!] Request error (403) when getting music data from https://stippling.bandcamp.com/album/perfect-life

The above request, but printed via a loop over the returned request object from ./requests/requester.py:24

__attrs__: ['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request']
__bool__: <bound method Response.__bool__ of <Response [403]>>
__class__: <class 'requests.models.Response'>
__delattr__: <method-wrapper '__delattr__' of Response object at 0x7f2be88583b0>
__dict__: {'_content': b'\n<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html>\n  <head>\n    <title>403 Forbidden</title>\n  </head>\n  <body>\n    <h1>Error 403 Forbidden</h1>\n    <p>Forbidden</p>\n    <h3>Error 54113</h3>\n    <p>Details: cache-pao-kpao1770042-PAO 1724995931 1303400507</p>\n    <hr>\n    <p>Varnish cache server</p>\n  </body>\n</html>\n', '_content_consumed': True, '_next': None, 'status_code': 403, 'headers': {'Connection': 'close', 'Content-Length': '425', 'Server': 'Varnish', 'Retry-After': '0', 'Content-Type': 'text/html; charset=utf-8', 'Accept-Ranges': 'bytes', 'Date': 'Fri, 30 Aug 2024 05:32:11 GMT', 'Via': '1.1 varnish', 'X-Served-By': 'cache-pao-kpao1770042-PAO', 'X-Cache': 'MISS', 'X-Cache-Hits': '0', 'X-Timer': 'S1724995931.197858,VS0,VE0'}, 'raw': <urllib3.response.HTTPResponse object at 0x7f2be9023310>, 'url': 'https://stippling.bandcamp.com/album/perfect-life', 'encoding': 'utf-8', 'history': [], 'reason': 'Forbidden', 'cookies': <RequestsCookieJar[]>, 'elapsed': datetime.timedelta(microseconds=171847), 'request': <PreparedRequest [GET]>, 'connection': <requests.adapters.HTTPAdapter object at 0x7f2be8fc0bf0>}
__dir__: <built-in method __dir__ of Response object at 0x7f2be88583b0>
__doc__: The :class:`Response <Response>` object, which contains a
    server's response to an HTTP request.

__enter__: <bound method Response.__enter__ of <Response [403]>>
__eq__: <method-wrapper '__eq__' of Response object at 0x7f2be88583b0>
__exit__: <bound method Response.__exit__ of <Response [403]>>
__format__: <built-in method __format__ of Response object at 0x7f2be88583b0>
__ge__: <method-wrapper '__ge__' of Response object at 0x7f2be88583b0>
__getattribute__: <method-wrapper '__getattribute__' of Response object at 0x7f2be88583b0>
__getstate__: <bound method Response.__getstate__ of <Response [403]>>
__gt__: <method-wrapper '__gt__' of Response object at 0x7f2be88583b0>
__hash__: <method-wrapper '__hash__' of Response object at 0x7f2be88583b0>
__init__: <bound method Response.__init__ of <Response [403]>>
__init_subclass__: <built-in method __init_subclass__ of type object at 0x5583e4730f50>
__iter__: <bound method Response.__iter__ of <Response [403]>>
__le__: <method-wrapper '__le__' of Response object at 0x7f2be88583b0>
__lt__: <method-wrapper '__lt__' of Response object at 0x7f2be88583b0>
__module__: requests.models
__ne__: <method-wrapper '__ne__' of Response object at 0x7f2be88583b0>
__new__: <built-in method __new__ of type object at 0x7f2beae3e4a0>
__nonzero__: <bound method Response.__nonzero__ of <Response [403]>>
__reduce__: <built-in method __reduce__ of Response object at 0x7f2be88583b0>
__reduce_ex__: <built-in method __reduce_ex__ of Response object at 0x7f2be88583b0>
__repr__: <bound method Response.__repr__ of <Response [403]>>
__setattr__: <method-wrapper '__setattr__' of Response object at 0x7f2be88583b0>
__setstate__: <bound method Response.__setstate__ of <Response [403]>>
__sizeof__: <built-in method __sizeof__ of Response object at 0x7f2be88583b0>
__str__: <method-wrapper '__str__' of Response object at 0x7f2be88583b0>
__subclasshook__: <built-in method __subclasshook__ of type object at 0x5583e4730f50>
__weakref__: None
_content: b'\n<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html>\n  <head>\n    <title>403 Forbidden</title>\n  </head>\n  <body>\n    <h1>Error 403 Forbidden</h1>\n    <p>Forbidden</p>\n    <h3>Error 54113</h3>\n    <p>Details: cache-pao-kpao1770042-PAO 1724995931 1303400507</p>\n    <hr>\n    <p>Varnish cache server</p>\n  </body>\n</html>\n'
_content_consumed: True
_next: None
apparent_encoding: ascii
close: <bound method Response.close of <Response [403]>>
connection: <requests.adapters.HTTPAdapter object at 0x7f2be8fc0bf0>
content: b'\n<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html>\n  <head>\n    <title>403 Forbidden</title>\n  </head>\n  <body>\n    <h1>Error 403 Forbidden</h1>\n    <p>Forbidden</p>\n    <h3>Error 54113</h3>\n    <p>Details: cache-pao-kpao1770042-PAO 1724995931 1303400507</p>\n    <hr>\n    <p>Varnish cache server</p>\n  </body>\n</html>\n'
cookies: <RequestsCookieJar[]>
elapsed: 0:00:00.171847
encoding: utf-8
headers: {'Connection': 'close', 'Content-Length': '425', 'Server': 'Varnish', 'Retry-After': '0', 'Content-Type': 'text/html; charset=utf-8', 'Accept-Ranges': 'bytes', 'Date': 'Fri, 30 Aug 2024 05:32:11 GMT', 'Via': '1.1 varnish', 'X-Served-By': 'cache-pao-kpao1770042-PAO', 'X-Cache': 'MISS', 'X-Cache-Hits': '0', 'X-Timer': 'S1724995931.197858,VS0,VE0'}
history: []
is_permanent_redirect: False
is_redirect: False
iter_content: <bound method Response.iter_content of <Response [403]>>
iter_lines: <bound method Response.iter_lines of <Response [403]>>
json: <bound method Response.json of <Response [403]>>
links: {}
next: None
ok: False
raise_for_status: <bound method Response.raise_for_status of <Response [403]>>
raw: <urllib3.response.HTTPResponse object at 0x7f2be9023310>
reason: Forbidden
request: <PreparedRequest [GET]>
status_code: 403
text: 
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <title>403 Forbidden</title>
  </head>
  <body>
    <h1>Error 403 Forbidden</h1>
    <p>Forbidden</p>
    <h3>Error 54113</h3>
    <p>Details: cache-pao-kpao1770042-PAO 1724995931 1303400507</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>

url: https://stippling.bandcamp.com/album/perfect-life

I do not know what is different about the request from a standard web browser request, so I cannot directly help, as that is not my forte.