pyicloud: Authentication required for Account. (421) when trying to query api.calendar.events()

The problem

I’m trying to retrieve calendar data from iCloud. I can authenticate successfully using the sample 2fa/2sa code. I can successfully call some of the APIs such as api.iphone.location(). However, when trying the following code, I get an error “pyicloud.exceptions.PyiCloudAPIResponseException: Authentication required for Account. (421)”.

from_dt = datetime(2021, 3, 27)
to_dt = datetime(2021, 3, 28)
events = api.calendar.events(from_dt, to_dt)

Environment

  • pyiCloud release with the issue (pip show pyicloud): 0.10.2
  • Last working pyiCloud release (if known): N/A
  • Service causing this issue:
  • Python version (python -V): Python 3.7.1 64-bit
  • Operating environment (project deps/Docker/Windows/etc.): macOS 11.2.3

Traceback/Error logs

DEBUG:pyicloud.services.calendar.http:GET https://p17-calendarws.icloud.com:443/ca/events 
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): p17-calendarws.icloud.com:443
DEBUG:urllib3.connectionpool:https://p17-calendarws.icloud.com:443 "GET /ca/events?lang=en-us&usertz=Europe%2FSofia&startDate=2021-03-27&endDate=2021-03-28 HTTP/1.1" 421 0
DEBUG:pyicloud.base:Saved session data to file
DEBUG:pyicloud.base:Cookies saved to /var/folders/vj/x_87xd5j5tz71ntl61101tfm0000gn/T/pyicloud/XXXXXX/XXXXXX
DEBUG:pyicloud.services.calendar.http:Misdirected Request (421). Retrying ...
DEBUG:requests.sessions.http:GET https://p17-calendarws.icloud.com:443/ca/events 
DEBUG:urllib3.connectionpool:https://p17-calendarws.icloud.com:443 "GET /ca/events?lang=en-us&usertz=Europe%2FSofia&startDate=2021-03-27&endDate=2021-03-28 HTTP/1.1" 421 0
DEBUG:pyicloud.base:Saved session data to file
DEBUG:pyicloud.base:Cookies saved to /var/folders/vj/x_87xd5j5tz71ntl61101tfm0000gn/T/pyicloud/XXXXXX/XXXXXX
ERROR:pyicloud.base:Authentication required for Account. (421)
Traceback (most recent call last):
  File "/Users/radoystoyanov/Documents/Code/alchemy-pipeline/calendars/icloud.py", line 67, in <module>
    events = api.calendar.events(from_dt, to_dt)
  File "/Users/radoystoyanov/Documents/Code/alchemy-pipeline/calendars/lib/python3.7/site-packages/pyicloud/services/calendar.py", line 65, in events
    self.refresh_client(from_dt, to_dt)
  File "XXXXXX/lib/python3.7/site-packages/pyicloud/services/calendar.py", line 58, in refresh_client
    req = self.session.get(self._calendar_refresh_url, params=params)
  File "XXXXXX/lib/python3.7/site-packages/requests/sessions.py", line 555, in get
    return self.request('GET', url, **kwargs)
  File "XXXXXX/lib/python3.7/site-packages/pyicloud/base.py", line 128, in request
    return self.request(method, url, **kwargs)
  File "XXXXXX/lib/python3.7/site-packages/pyicloud/base.py", line 130, in request
    self._raise_error(response.status_code, response.reason)
  File "XXXXXX/lib/python3.7/site-packages/pyicloud/base.py", line 186, in _raise_error
    raise api_error
pyicloud.exceptions.PyiCloudAPIResponseException: Authentication required for Account. (421)

Additional information

I have including additional debug logging using:

logging.basicConfig(level=logging.DEBUG)

Thanks in advance for your support!

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 8
  • Comments: 15

Most upvoted comments

After comparing the request fired at browser to the payload generated at pyicloud, i found that param dsid is lost and it causes 419 http error.

To fix the problem, you can append the following code to pyicloud/services/calendar.py:L55

        params.update(
            {
                "lang": "en-us",
                "usertz": get_localzone().zone,
                "startDate": from_dt.strftime("%Y-%m-%d"),
                "endDate": to_dt.strftime("%Y-%m-%d"),
                "dsid": self.session.service.data["dsInfo"]["dsid"],  # PATCH HERE!!
            }
        )

The monkeypatch is working for me. If this is generally a working solution, please merge soon.