iCloud CardDAV returns 401 with fresh app-specific password — also reproducible with vdirsyncer

Hi,

I’m trying to access my own iCloud Contacts via CardDAV from a self-hosted web application.

Apple’s documentation still states that app-specific passwords can be used for third-party access to iCloud Contacts when the app does not support Apple’s newer authorization flow.

However, authentication currently fails consistently with HTTP 401 at the very first CardDAV request.

Setup:

Apple Account with 2FA enabled correct Apple Account ID / iCloud address freshly generated app-specific password CardDAV endpoint: https://contacts.icloud.com/

HTTP Basic Auth read-only PROPFIND requesting current-user-principal

I have reproduced the same result with three independent clients:

my own PHP/libcurl implementation a minimal direct cURL/libcurl reference request vdirsyncer 0.21.0

vdirsyncer fails during discovery with: 401 Unauthorized

https://contacts.icloud.com/.well-known/carddav In my direct request, Basic Authorization is definitely sent and the server responds 401 before any redirect or personal CardDAV shard discovery occurs.

I have also verified:

no username mismatch no redirect/auth-header loss no HTTP/1.1 vs HTTP/2 issue no password transformation by the application a fresh app-specific password was copied directly from Apple and tested immediately

Interestingly, direct CardDAV access for this same project/account worked previously, so CardDAV itself has worked for this account before. Has anything changed recently regarding authentication to iCloud Contacts/CardDAV?

Specifically:

Are app-specific passwords still expected to authenticate directly against contacts.icloud.com? Is there any additional account setting or authorization required now? Is .well-known/carddav still the supported discovery route?

Is Apple’s newer “Account Data Sharing” authorization available to independent/self-hosted applications for iCloud Contacts, and if so, is there developer documentation for that flow?

I’m deliberately not asking about writing contacts yet — this is only a read-only CardDAV authentication/discovery test.

Thanks for any pointers.

Cheers, Vince

iCloud CardDAV returns 401 with fresh app-specific password — also reproducible with vdirsyncer
 
 
Q