Hi Team,
I'm trying to understand the behavior of the following API:
HTTPCookieStorage.shared.setCookies(_:for:mainDocumentURL:)
Specifically, does this API persist cookies synchronously, or does it perform the storage asynchronously in the background?
Our use case is storing FCAP (frequency capping) cookies so they persist across app sessions. We call setCookies(_:for:mainDocumentURL:) and want to know whether the cookies are guaranteed to be written before the method returns, or if the actual persistence happens asynchronously.
I couldn't find documentation describing the persistence semantics of this API, so I'd appreciate any clarification or guidance from Apple or anyone familiar with its implementation.
Thanks
Thanks for asking. You are right that the reference does not state the persistence semantics. Here is what is documented, and what is only observed.
On synchronous versus asynchronous: nothing classifies the call, not the reference, not the Foundation SDK header (NSHTTPCookieStorage.h), and not the cookie standards. The method returns no value and takes no completion handler, and nothing documents when the change becomes visible or when it reaches disk. The standards do not answer it either, since they define the cookie model, not the timing of an API call. So there is no contract to depend on in either direction.
I can offer an observation, but not a guarantee: on macOS and on iOS 26.5, a cookies or cookies(for:) read on the same storage immediately after setCookies(_:for:mainDocumentURL:) returned the cookies every time. Because that behavior is undocumented, it is subject to change without notice at any time. I would treat it as current behavior on the versions I tested, not something to rely on.
On persistence across app sessions, the behavior follows the standard cookie model, and here there is a rule you can rely on. Under RFC 6265, a cookie is persistent only if it carries a Max-Age or Expires attribute. A cookie with neither is a session cookie, and the client is required to discard it once the session ends. Foundation reflects this: a cookie with no expiration date reports isSessionOnly == true. The documentation describes such a cookie as discarded at the end of the session, regardless of expiration date. So an expiration date is what makes a cookie persist beyond the session, by the standard rather than as an implementation detail. Testing on iOS 26.5 matched this. A cookie with an expires date survived a relaunch, including after the previous instance was force-terminated. A session-only cookie was gone in the next launch.
So if cookies are not surviving across sessions, the first thing to check is whether they carry an expiration date. To store one that persists, give it an expires date when you create it (or a Max-Age / Expires attribute in the response headers you build it from). Then confirm the storage's cookieAcceptPolicy is not .never, and that the domain and path match what you later read.
The dependable part is that lifetime rule: session versus persistent is the standard cookie behavior, and isSessionOnly reflects it. The synchronicity and the exact write timing are not specified anywhere. I would not depend on them beyond what you can observe on the OS versions you test.
For reference:
- https://developer.apple.com/documentation/foundation/httpcookiestorage/setcookies(_:for:maindocumenturl:)
- https://developer.apple.com/documentation/foundation/httpcookie/issessiononly
- https://developer.apple.com/documentation/foundation/httpcookie/expiresdate
- https://developer.apple.com/documentation/foundation/httpcookiestorage