Reincubate iCloud API support

Our tutorials, sample code and FAQs.

Support centre › Reincubate iCloud API support

This documentation covers the legacy release of Reincubate’s ricloud API. Documentation for the 2017 release is available here.


The Reincubate iCloud API makes the iCloud accessible to investigators, developers and integrators. The API includes functionality for extraction, manipulation and recovery of many types of iOS and app data.

It has functionality to support bulk, scheduled, and realtime data access. It is RESTful and makes many commonly accessed forms of data available as JSON feeds.

It fully supports iOS 9 and iOS 10 Beta CloudKit-based iCloud backups, and backups created with A9 chipsets. It can provide real-time iCloud data for a number of datatypes, and supports undeletion of content which has been previously erased from the iCloud.

Who uses the API, and is it secure?

The API is hosted, delivered and developed in the UK and US by Reincubate, makers of the first iOS data extraction product, the iPhone Backup Extractor. The company is subject to stringent UK data protection legislation, and is compliant with EU and US Safe Harbor regulations.

Reincubate are trusted by security, LEA and government users around the world. The company publishes a select few testimonials on the API's product information page, and the enterprise team can arrange references for potential users.

Clients put the API to a number of uses, including:

  • Compliance: connecting corporations with data on their device inventories.
  • CRM and point-of-sale (POS) integration: connecting stores and sales teams with data on their clients calls and messages.
  • Child protection: allowing parents to safeguard their childrens' online activity.
  • Law enforcement and forensics: allowing law enforcement and security agents to access information on devices and accounts of interest.

What level of data access does the API provide?

The API provides access to all raw iCloud files and data. It also provides access to a number of JSON feeds, use of which is recommended over raw file access.

What benefits does Reincubate's iCloud API provide?

The API -- and in particular, the feeds -- provide a number of substantial benefits:

  • Ease of integration. The API is easy for development teams at any level to work with, and they remove the need for clients to have any highly specialist knowledge about either iCloud / CloudKit storage, or about any third-party apps.

    This benefit is not easily overstated: the complexity of developing and maintaining an interface to the iCloud is substantial, and layered on top of that is the need to support multiple data formats for core iOS data and app files. Not only does iOS use different data formats, but each app (for instance, WhatsApp), uses a set of data formats and structures which can change week-to-week with app updates.

    The API supports all the "difficult" features: iOS 9, iOS 10 Beta, CloudKit, iCloud 8 + 9 merging, 2SV/2FA, partial snapshots, tokenisation, A9 & A9X.

  • Future proofing. Reincubate is committed to maintaining support for contemporary and past iCloud and iOS data formats, and has a solid track record in this space:

    • 1st to support iOS data access (2008)
    • 1st to support encrypted iOS data access (2009)
    • 1st to support iCloud data extraction (2011)
    • 1st & only with an API to support iCloud / CloudKit iOS 9 data access (2015)
  • Support & access to unrivalled expertise. As a consequence of the company's focus and positioning as the app data company, Reincubate's team have unrivalled experience and knowledge in the field. This experience is particularly valuable for clients exploring new apps and use-cases.

    Users of the JSON feeds are able to take advantage of Reincubate's proprietary techniques in extraction and undeletion of app data, such that the resultant data is more accurate.

  • Out of the box app support. Aside from the core iOS datatypes -- all of which are supported across all iOS versions on all devices -- the API has modules to support dozens of third-party apps. Some of the more popular supported apps include WhatsApp, Viber, Kik, WeChat, Line, SnapChat, Facebook Messenger and Skype.

  • Out of the box developer platform support. The API has open source client implementations available in a number of languages, including Python, .NET / C# and JavaScript.

  • Speed & scalability. The Reincubate iCloud API platform is built to scale, and the JSON feed system faster and scales better than raw file access.

  • Rich feed customisation options. The feed platform is readily customisable for partner deployments. Examples include protobuf format feeds and aggregation of messaging app attachments.

  • Trust. Reincubate are trusted by security, LEA and government users around the world. The company is subject to stringent UK data protection legislation, and is compliant with EU and US Safe Harbor regulations.

Getting started

Interested parties can contact the enterprise team for access to an API key. However, a test key is provided in all of the sample client implementations.

The test key user value is 120455 and the key value is 1413537101. This key will only permit access to listing installed apps, and is rate-limited.

Installing the sample Python client

The Python iCloud library can be installed with a single command:

$ pip install ricloud

Source for this client can be found on GitHub under ricloud-py.

Installing the sample JavaScript client

The JavaScript iCloud library can be installed with a single command:

$ npm install ricloud

Source for this client can be found on GitHub under ricloud-js.

Installing the sample .NET / C# client

The C# iCloud library can be installed with a single command:

$ nuget install ricloud

Source for this client can be found on GitHub under ricloud-csharp.


Each client implementation comes with its own set of bundled documentation, and a sample script which shows how it can be used. Configuration is usually limited to specifying a user and key value for authentication against the API.

Working with the API

Note that the sample client implementations handle much of the complexity shown below, without the developer needing to get involved. The curl methods below are shown for developers who wish to dig into the fundamentals of the API, or to build their own native clients.

There are three core operations that a user may need to perform with the API.

  • Authentication and enumeration: sign-in, perform-2fa-challenge, submit-2fa-challenge
  • Feed data access: download-data
  • Raw file access: download-file

Some clients may have access to additional methods and endpoints as part of their deployment.

Examples in this section are given in curl format.

On all requests made to the API, curl must be told to follow redirects with the -L parameter. The user's API credentials must also be set with --user "USER:KEY", as must the custom API version header, --header "Accept: application/vnd.icloud-api.v1". So all curl calls in these examples must start with:

curl -L
     -X POST
     --user "USER:KEY"
     --header "Accept: application/vnd.icloud-api.v1"

Note that the -X POST option is also specified, as all the requests are made through POST. As this call isn't going to change, it is referred to below as CURL_CALL.

Depending on the nature of a client's API implementation, it may be necessary to respect a concurrency limit across different types of requests to the API.

As a general guideline, all requests (except errors) return a session_key field which identifies the current session. If it isn't sent, a sign-in request should be used to generate a new session. session_key values should be used consistently.

Once a session_key has been obtained, it will be reliably valid for at least 30 minutes between calls.

1. Authentication, 2FA/2SV and retrieval of device & data list

In order to sign in as a user with two-factor authentication or two step verification enabled on his account, the sign-in method must be used.

CURL_CALL --data-urlencode "email=ICLOUD_EMAIL"
          --data-urlencode "password=ICLOUD_PASSWORD"

The email and password of the iCloud account to access are passed as parameters, using --data-urlencode to ensure that control characters such as @ are escaped.

Signing in with an invalid API keypair

If a user makes a request of the API with an invalid keypair, it will return no data beyond a 403.


Signing in to an account where the end-user has not accepted iCloud T&Cs

If the user attempts to sign in to an iCloud account for which an updated set of iCloud terms and conditions haven't been accepted.

 "error": "terms-of-service-update",
 "message": "User hasn't agreed to Apple's Terms of Service."

Signing in with bad iCloud credentials

If a user attempts to sign in with bad iCloud credentials, a 403 will be returned along with an error message.

{"message": "Unsuccessful login attempt:",
 "error": "unable-to-login"}

Signing in to an account which the end-user has not validated

If the user attempts to sign in to an iCloud account for which the primary email hasn't been validated by the user.

 "error": "unverified-account",
 "message": "User's primary email hasn't been verified."

Signing in without 2FA/2SV

Signing in on a non-2FA account can be done with a single request.

HTTP/1.1 200 OK
 {"7c7fba66680ef796b916b067077cc246adacf01d": {
    "ios_version":   "9.0.1",
    "colour":        "#e4e7e8",
    "device_name":   "Renate's iPhone",
    "latest-backup": "2015-11-17 16:46:39.000000",
    "model":         "N71mAP",
    "serial":        "D56DF63DYTBG",
    "name":          "iPhone 6s"},
 "8e281be6657d4523710d96341b6f86ba89b56df7": {
    "ios_version":   "9.1",
    "colour":        "#e1e4e3",
    "device_name":    "Renate's iPad",
    "latest-backup": "2015-11-13 19:35:52.000000",
    "model":         "J98aAP",
    "serial":        "E32VR64AFXVF",
    "name":          "iPad Pro"},
 "key": "b3d11d6c-52c0-4754-a971-8f305047a0f6",
 "auth_token": "N28GZaKvTXAGrhBIx3UgRGml47oPVCCq4tqM5huyCKo2r7h2HfMtyBsZVc3SS2sh5h3I"}

Signing in with 2SV/2FA

If the account was secured with two-factor authentication, the sign-in the request will return a error message stating that two-factor authentication is enabled on this account, the session_key and, in the case of 2SV, also a list of trustedDevices.

  • 2SV
{"message": "This account has Two Step Verification enabled, please select a device to challenge.",
 "data": {
  "trustedDevices": ["********12", "Renate's iPhone - iPhone 6s"],
  "key": "b3d11d6c-52c0-4726-a971-8f305047a0f6"
 "error": "2fa-required"

For 2SV, The next step is to issue a 2SV challenge code to one of the trustedDevices. To do this a request is made to perform-2fa-challenge.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "challenge=DEVICE_TO_CHALLENGE"

The parameters that sent are challenge, which must contain on the items listed on trustedDevices, and the session_key, which will be the same as the sign-in request returned.

  • 2FA

In the case of 2FA, the difference is that the request will return an empty trustedDevices list.

{"message": "This account has Two Factor authentication enabled, all devices will be challenged.",
 "data": {
  "trustedDevices": ["Challenge all 2FA devices"],
  "key": "b3d11d6c-52c0-4726-a971-8f305047a0f6"
 "error": "2fa-required"

For 2FA, we don't get to choose which device is challenged, as every trusted device will automatically be challenged. To do this a request is made to perform-2fa-challenge, without the challenge argument.

CURL_CALL --data-urlencode "key=SESSION_KEY"

Therefore, for 2FA the only parameters that is sent is the session_key, which will be the same as the sign-in request returned.

Challenging with a bad device (2FA/2SV)

If a user makes a request of the API with an invalid device, it will return no data beyond a 500.


Challenging with a bad key (2FA/2SV)

If a user makes a request of the API with an invalid key, it will return a 403 with a validation message.

{"message": "Your iCloud session has expired. To continue, please sign in again.",
 "error": "key-invalid"}

Challenging successfully (2FA/2SV)

HTTP/1.1 200 OK
{"message": "Challenge has been submitted."}

Once the challenge has been sent to the user's device, the data sent must be relayed back to the API using submit-2fa-challenge.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "code=2FA_CODE"

Submitting a bad challenge response (2FA/2SV)

{"message": "Incorrect code supplied for Two Factor Authentication.",
 "error": "invalid-2fa-code"}

Submitting the right challenge response (2FA/2SV)

HTTP/1.1 200 OK
{"message": "Challenge has been submitted."}

With this request, the user will be fully authenticated and the API session will be active.

To complete the login process and retrieve the device list, submit a final request to sign-in using the same email and password as the first request and using the same key used through the 2FA/2SV authentication process.

Note, the response will only contain the auth_token entry if your API key has tokenisation enabled. In this case we recommend you submit the final request to refresh-session as outlined in Section 4 below, instead of submitting it to sign-in. Using the auth_token is more robust as it is an indicator of an already established session on Apple's systems.

On the new API backend adaptor you should expect to see a different response. This is due to optimisations in the flow of the 2FA/2SV process.

HTTP/1.1 200 OK
{"key": "b3d11d6c-52c0-4726-a971-8f305047a0f6",
"message": "Log-in successful",
"auth_token": "N28GZaKvTXAGrhBIx3UgRGml47oPVCCq4tqM5huyCKo2r7h2HfMtyBsZVc3SS2sh5h3I"

2. Retrieval of feed data: download-data

The download-data method is used to access feed data.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "device=DEVICE_ID"
          --data-urlencode "mask=DATA_MASK"
          --data-urlencode "since=MIN_DATE"

The parameters needed for this request are the current session_key, the device_id of one of the devices from the login response, and the data_mask, which is an OR combination of all the feed module flags the user is interested in. You can also specify a since date from which to start looking for data.

The API consistently uses dates in the ISO-8601 format, in the UTC timezone. For example, 24th December would be expressed as 2014-12-24 17:30:00.000000.

Assuming the client's API key is valid for all of these modules, the method will return the requested data in JSON format.

See the section below for documentation on and examples of the JSON formats.

Submitting a valid feed request

If the values passed to the method are valid, it will return the feed content in the HTTP response body.

HTTP/1.1 200 OK

Submitting a feed request with missing parameters

If one of the required parameters is missing, the method will return a bad request response code.

{"message": "mask missing from post.",
 "error": "invalid-request"

Submitting a feed request with invalid parameters

If an invalid or misformatted value is submitted for any parameter, the method will return a bad request response code.

{"message": "Invalid since.",
 "error": "invalid-parameter"

Sample feed module flags

The following module flags can be masked together for the mask parameter of the download-data method. This is not an exhaustive list.

  • 0000001 Messages
  • 0000002 Photos and videos
  • 0000004 Browser history
  • 0000008 Call history
  • 0000016 Contacts
  • 0000032 Installed apps
  • 0000064 Contacts (live)
  • 0000128 Photos and videos (live)
  • 0000256 Location (live)
  • 0000512 WhatsApp messages
  • 0001024 Skype messages
  • 0002048 Calendar
  • 0004096 Line messages
  • 0008192 Kik messages
  • 0016384 Viber messages
  • 0032768 Facebook messages
  • 0065536 WeChat messages
  • 0131072 Snapchat messages
  • 0262144 File list
  • 0524288 Browser history (live)
  • 1048576 WhatsApp call history
  • 2097152 Viber call history
  • 4194304 App usage
  • 8388608 Notes

The feed modules marked as live above are real-time datasets. The other data is point-in-time from backup data. Access to the live feed modules can trigger an email being sent to the account's owner.

For instance, to request a feed of messages, call history and browser history, the mask would be 1 + 4 + 8 = 13.

JSON feed formats

The JSON feeds are designed to be as simple to parse as possible. The feed will return all of the data types requested within a single response.

Each feed module specified in the module flag will have its own key in the top level JSON dictionary that is returned.

    "first_module_name": "Module's data",
    "second_module_name": "Module's data",
    "etc.": "etc."
Messages (all messaging apps)

Messaging apps will return data as an array of messaging objects each containing the following keys:

  • id The ID of the message. This field is internal to the messaging app, unique only in the context of that app, and may not be an integer. Deleted messages do not have unique IDs, as the field is set is -1 for those records.
  • conversation_id The ID of the messaging thread. Like id this is internal and may not be an integer. For iOS messaging, this may be set by the sender (for instance, vodafone, or it may be arbitrary, like chat1122932342342.
  • date The date that the message was sent or received. For instance, 2015-10-28 09:18:17.000000.
  • text The body of the message. This can be a string or null.
  • from_me A boolean value to indicate whether the message was sent or received.
  • user (Optional.) The user of the messaging app in the case where multiple users/accounts may be using a messaging app from the device.
  • type (Optional.) Types include SMS, iMessage.
  • deleted (Optional.) A boolean value to indicate whether the message had been deleted.
  • handle The 2nd party of the conversation, this may be the group name.
  • contact (Optional.) An object referencing an iOS contact of the 2nd party of the conversation.
  • group (Optional.) The name of the group when the message was sent.
  • group_id (Optional.) The unique identifier for the group within the context of that app. This may not be an integer, and if present, only provides information in addition to conversation_id.
  • group_handles This value is null for person-to-person messages, and in group conversations is an array of strings representing phone numbers or iMessage email addresses.
  • group_contacts (Optional.) An array of objects referencing iOS contacts in the group.
  • attachments An array of file_id values which can be used with the download_file method. If the message includes no attachment, an empty array is returned.

Deleted messages will only appear for customers with the undeletion module active on their key.

Messaging apps will return the data in the format defined above, but under different keys:

  • sms including SMS, MMS and iMessage
  • whatsapp_messages
  • skype_messages
  • line_messages
  • kik_messages
  • viber_messages
  • facebook_messages
  • wechat_messages

There are some caveats around use of Facebook Messenger and Snapchat data; please contact the enterprise team to learn more.

An example JSON response containing a single message is shown below.

    "sms": [
            "group_handles": [
            "attachments": [],
            "deleted": false,
            "text": "Don't forget. Get a \u00a35 Bonus Credit to use for 7 days when you top up by \u00a310 or more in one go by 29/10/15. Your Bonus Credit will usually be added to your balance within 24hrs of your top up. Terms apply. To stop SMS text STOP to 9774.",
            "conversation_id": "vodafone",
            "from_me": false,
            "date": "2015-10-28 09:18:17.000000",
            "handle": "vodafone",
            "type": "SMS",
            "id": 6
Photos and videos

Photos and videos are presented under the photos key. iCloud Photo Library data is presented under web_photos. The iCloud Photo Library data currently makes no distinction between files listed on the iCloud photolibrary website and unlisted 'deleted' files, that are not visible on the iCloud website but are still downloadable from the Apple servers.

    "photos": [
            "file_id": "343e26971dfe9c395c425c0ccf799df63ae6261e",
            "filename": "IMG_0001.JPG"
    "web_photos": [
          "filename": "IMG_0006.JPG",
          "file_id": 1,
          "size": 1878590
Browser history

Browser history is presented under the browser_history or web_browser_history (live feed) keys.

    "browser_history": [
            "url": "",
            "last_visit": "2015-09-10 10:30:53.413244",
            "title": " Low Prices in Electronics, Books, Sports Equipment & more"
Call history

Call history is presented under the call_history, whatsapp_call_history or viber_call_history keys.

    "call_history": [
            "duration": 5.0,
            "answered": false,
            "from_me": true,
            "date": "2015-07-20 10:23:27.538011",
            "address": "07123456789",
            "call_type": "Phone"

Backup contacts are presented under the contacts key, and live contacts are presented under web_contacts.

    "contacts": [
            "records": [
                    "type": "Phone",
                    "value": "1-800-MY-APPLE"
                    "type": "URL",
                    "value": ""
            "first_name": "John",
            "last_name": "Appleseed",
            "organisation": null,
            "modified": "2015-09-14 11:59:17.000000",
            "created": "2015-09-14 11:59:10.000000",
            "id": 17
Installed apps

Installed apps are presented under the installed_apps key.

    "installed_apps": [
            "name": "FaceTime",
            "description": "FaceTime for Mac makes it easy to talk, smile and laugh with friends and family on their iPhone 4, iPad 2, iPod touch or Mac. Getting started is quick and easy \u2014 simply enter your Apple ID and you're ready to go.\u00a0Whether you're talking to someone on an iPhone or on another Mac, video calls with FaceTime look great. There's no better way to keep all your favorite faces just a click away.\n\nSimple to Get Started\n\u2022 Setup is quick and easy \u2013 just enter your Apple ID.\n\u2022 With just one click, you can make a video call to an iPhone 4, iPad 2, iPod touch, or another Mac. \n\nEasy-to-Organize Contacts\n\u2022 Make calls using your existing Address Book contacts \u2013 you don\u2019t have to enter your contacts from scratch.\n\u2022 Add the people you call most often to your Favorites list.\n\u2022 Quickly review your past calls with Recents.\n\nHigh-Definition Video\n\u2022 Receive HD video calls at up to 720p on supported, Intel-based Macs.*\n\u2022 A Mac with a standard-definition camera delivers up to VGA-quality video for Mac-to-Mac calls.\n\nElegant Interface\n\u2022 Window and playback controls fade away so the focus stays on your conversation.\n\u2022 View transitions smoothly when an iPhone 4, iPad 2, or iPod touch user switches from front to rear cameras or from portrait to landscape views.\n\u2022 FaceTime's widescreen aspect ratio makes it easy for families and groups to participate in a call.\n\u2022 Enjoy your video call full screen, using every inch of your beautiful Mac display.\n\nRing Anywhere, Any Time\n\u2022 Incoming calls ring on your Mac, even if FaceTime isn\u2019t running.\n\u2022\u00a0If you have more than one Mac, incoming calls ring on every one so you can answer on the Mac that\u2019s most convenient.\n\n*Video calls require a built-in FaceTime camera, an iSight camera (built-in or external), a USB video class (UVC) camera, or a FireWire DV camcorder; and a 128-Kbps upstream and downstream Internet connection. Making HD video calls requires a built-in FaceTime HD camera and a 1-Mbps upstream and downstream Internet connection. Receiving HD video calls requires a supported Intel-based Mac. (for a complete list, visit",
            "advisory-rating": "4+",
            "author": "Apple",
            "store_url": "",
            "artwork_url": ""

Location data is presented under the location key.

    "location": [
            "model": "iPhone8,2", 
            "fmip_id": "1V2C61z2pjGNtKndMq0tkKCnYxstP/eDRZcxqt9e64k+Yw7qRZ7IBuHYVNSUzmWV", 
            "location": {
                "latitude": 51.51438464604969, 
                "date": "2016-09-27 10:41:26.058000", 
                "longitude": -0.09078322232611295
            "name": "RI iP6s+ iOS10 White"

If location data is temporarily unavailable for a device, the location key will contain a null value. This indicates that Apple has no current location information, but the field will be populated with data as soon as the device starts reporting again.


Calendar data is presented under the calendar_appointments key.

    "calendar_appointments": [
            "attached_url": null,
            "attendees": null,
            "description": null,
            "end_date": "2014-08-15 14:30:00.000000",
            "start_time_zone": "Europe/London",
            "all_day": false,
            "summary": "Another appointment",
            "recurrence": {
                "specifier": "",
                "repeat": "Weekly",
                "interval": 1,
                "repeat_end_date": null
            "travel_time": null,
            "id": 73,
            "location": null,
            "end_time_zone": "Europe/London",
            "start_location": null,
            "calendar": "Work",
            "creation_date": "2014-08-22 13:23:20.000000",
            "start_date": "2014-08-15 13:30:00.000000"
File list

The available file list is presented under the file_list key.

    "file_list": [
            "file_id": "37194cdd973ff73e0d9547eb23b8d93510cbdeea",
            "filename": "IconState.plist"

Note data is presented under the notes key.

    "notes": [
            "creation_date": "2016-06-06 13:23:20.000000",
            "last_modified": "2016-06-07 15:21:25.000000",
            "title": "Monday meeting:",
            "note": "Monday meeting:\n Discuss X,\n discuss Y.",
            "summary": null,
            "attachments":  [
                                    "type": "image",
                                    "file_id": "8e22cf6e524357b4eb3da775d193072ebba9543f", 
                                    "file_path": "Media/80DDDEAD-B33F-37B2-7219432C0359/Image.jpeg",
            "folder": "iCloud",
            "sub_folder": "work",


3. Retrieval of raw files: download-file

The download-file method is available for downloading message attachments, or directly downloading more esoteric files from the iCloud.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "device=DEVICE_ID"
          --data-urlencode "file=FILE_ID"

          -o PATH_TO_SAVE_FILE

The parameters needed are the session_key, the target device_id, and a file_id. The request above will download the file and store it the path specified to curl with the -o option.

file_ids are either stored files in iCloud, or identifiers for hosted files on the internet. In the former case, file_ids are built from SHA-1 hashes of a file's AppDomain and filename. In the latter case we may process and decrypt the file before returning it.

file_ids may be previously known for static files, or can be obtained from message feeds, where they are used as identifiers by attachments.

As noted above, it is invariably better to use the JSON feeds when working with app data. The JSON feeds provide faster and more accurate data access.

Submitting a valid file request

If the values passed to the method are valid, it will return the binary file content in the HTTP response body.

HTTP/1.1 200 OK

Submitting a file request for a non-existent file

If a file is not present on the iCloud, or we cannot retrieve it from the appropriate third-party, the method will still return successfully, however the message body will be empty.

HTTP/1.1 200 OK

Submitting a file request after the session has expired

If the session has expired, clients will be served a bad request response code.

{"message": "Your iCloud session has expired. To continue, please sign in again.",
 "error": "key-invalid"}

Sample file_ids

Common hash keys associated with apps for direct file access include the following.

  • 3d0d7e5fb2ce288813306e4d4636395e047a3d28 SMS
  • 1b6b187a1b60b9ae8b720c79e2c67f472bab09c0 WhatsApp
  • 1c6a49018bcace96656e4fe8f08d572ce071b92c WhatsApp
  • 7c7fba66680ef796b916b067077cc246adacf01d WhatsApp
  • b39bac0d347adfaf172527f97c3a5fa3df726a3a Viber
  • 8e281be6657d4523710d96341b6f86ba89b56df7 Kik
  • ff1324e6b949111b2fb449ecddb50c89c3699a78 Calls
  • a49bfab36504be1bf563c1d1813b05efd6076717 Calls
  • 2b2b0084a1bc3a5ac8c27afdf14afb42c61a19ca Calls
  • 5a4935c78a5255723f707230a451d79c540d2741 Calls
  • 12b144c0bd44f2b3dffd9186d3f9c05b917cee25 Photos
  • adb8c77534444e97c31ff15924d50f3ed1fbd3b1 Contacts
  • 2041457d5fe04d39d0ab481178355df6781e6858 Appointments
  • 3ecf3efff3a55d6155efce2828579e8a3cd881c1 Browsing history
  • cd89f9e10d3497912bfc92e5dc674ca989cfdd44 Browsing history
  • 2d711a1f5613f5259730b98328a3f7e816698f88 Line

Some messenger applications -- such as Skype, Facebook Messenger and WeChat -- vary the file_id dependant on the conversation.

4. Refreshing an account login using authentication tokens

This is an additional method available to some clients. For access to this method contact the enterprise team.

The auth_token is a login token with Apple. It lasts for at least a day, and is refreshed when a request is made to the refresh-session endpoint on the API. A daily poll to the refresh-session endpoint is all that is needed to persist this token.

As the refresh-session endpoint only needs the auth_token as input and returns the device list plus a new session key, it can be used to start a new session on the API without the need to login to the account again. This is especially useful for 2FA/2SV enabled accounts as the authentication process only needs to be completed for the initial sign-in request.

To use it, one must use the auth_token field retrieved during login. This must be sent to the refresh-session endpoint.

The auth_token parameter is return from the initial sign-in request, and must be used against the refresh-session endpoint.

CURL_CALL --data-urlencode "auth_token=AUTHENTICATION_TOKEN"

Submitting an invalid authentication token

If the token is not valid, the endpoint will return a bad request code.

{"message": "Invalid auth_token.",
 "error": "invalid-parameter"}

Submitting a valid authentication token

The response will be similar to the login endpoint: a newly created session key and the updated list of devices with all the metadata needed to identify each. One can use the new session to continue pulling data.

HTTP/1.1 200 OK

5. Deletion of iCloud Photo Library files: delete-file

The delete-file method is available for deleting photos from the iCloud Photo Library. It accepts file, key and a permament flag as parameters.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "file=FILE_ID"
          --data-urlencode "permanent=False"

The file parameter will contain the photo's id (retrievable through the web_photos feed) and the permanent flag controls if the file is going to be soft or hard deleted. If it's set to False, the request will cause the file to be moved to the "Recently deleted" photos album (known as soft delete). On the other hand, if it's set to True, then the request will remove the file from the "Recently deleted" album, and will cause it to be deleted permanently (known as hard delete).

Successful soft delete

If the soft delete was successful, the photo will be moved to the "Recently deleted" album and it will return a success message.

HTTP/1.1 200 OK
  "message": "Success: File number: FILE_ID has been recycled."

Successful hard delete

If the hard delete was successful, the photo will be removed from associated devices when these devices next sync to iCloud. However, due to the technique used, hard deleted files will still be discoverable and downloadable from Reincubate's iCloud Photo API for an indeterminate amount of time. This behaviour can be used to un-delete unlisted files.

Please note that, for a file to be hard deleted, it must have been soft deleted first.

HTTP/1.1 200 OK
  "message": "Success: File number: FILE_ID has been deleted permanently."

Failed soft or hard delete

If the request fails, it will return an error response.

  "message": "Failure: File number: FILE_ID was not deleted."

Accelerating downloads with native SDK

This is an additional method available to some clients. For access to this method contact the enterprise team.

For highly parallelised file downloads, we offer a C++ SDK which allows clients to download and decrypt files locally, avoiding the overhead (but losing the convenience) of the download-file endpoint. This SDK is available for Linux (Ubuntu 12.04, Ubuntu 14.04, Debian Jessie), and Windows.

It is integrated with the rest of the API's workflow.


Users can load the current library and call DownloadFiles, the SDK entrypoint, which has the following signature:

int DownloadFiles(const wchar_t* clientID, const wchar_t* clientKey, const wchar_t* sessionKey,
                  const wchar_t* deviceID, const wchar_t** fileIDs, size_t fileIDs_count,
                  const wchar_t* targetDir, ProgressFunction progFunc, void* progParam,
                  GetWStringBuffer getErrorBuffer)

With these external callback definitions:

typedef wchar_t* (*GetWStringBuffer)(size_t size);
typedef bool(*ProgressFunction)(double percent, unsigned long long downloadedSize,
                                unsigned long long totalSize, void* param);

The parameters are:

  • clientID The API client ID.
  • clientKey The API client key.
  • sessionKey Current session key.
  • deviceID Target device ID.
  • fileIDs Array of required file_ids.
  • fileIDs_count Length of the fileIDs array.
  • targetDir Output directory where the files will be downloaded .
  • progFunc Progress callback function, which is called every time a progress update is made.
  • progParam Custom parameter that can be passed to the progFunc callback.
  • getErrorBuffer This callback function should return a buffer which will hold the errors occured during the download.

After the download finishes, the requested file ids will be in the folder designated by targetDir.

Older SDK versions

On older versions, the the DownloadFiles entrypoint had a slightly different signature:

int DownloadFiles(const wchar_t* clientID, const wchar_t* clientKey, const wchar_t* sessionKey,
                  const wchar_t* deviceID, const wchar_t** fileIDs, size_t fileIDs_count,
                  const wchar_t* targetDir, ProgressFunction progFunc, void* progParam,
                  GetWStringBuffer getReplyBuffer, GetWStringBuffer getErrorBuffer)

The additional parameter is:

  • getReplyBuffer Similar to getErrorBuffer, this callback function is responsible of returning a valid buffer where the DownloadFiles method can write. In this case, this buffer will contain the reply with a final status of the download.

Account and device deactivation and reactivation

This is an additional method available to some clients. For access to this method contact the enterprise team.

The client-management method allows for clients to deactive or reactivate billing for account or device access. The methods for deactivation and reactivation have separate endpoints.

Account deactivation
CURL_CALL --data-urlencode "account=ACCOUNT_ID"

Account reactivation
CURL_CALL --data-urlencode "account=ACCOUNT_ID"

Device deactivation
CURL_CALL --data-urlencode "device=DEVICE_ID"

Device reactivation
CURL_CALL --data-urlencode "device=DEVICE_ID"

Submitting a valid request

If the values passed to the account deactivation method are valid, it will return a message in the HTTP response body.

HTTP/1.1 200 OK
{"message": "deactivation has been set to True for account: ACCOUNT_ID"}

In the event of a user requesting a device be deactivated, a similar message is returned in the HTTP response body:

HTTP/1.1 200 OK
{"message": "deactivation has been set to True for device: DEVICE_ID"}

Submitting a request with invalid credentials

If the user makes a request to deactivate or reactivate an account with an invalid account_id or invalid device_id, or if the account_id or device_id are not associated with the user, it will return an HTTP 400.

{"message": "no device with device ID: BAD_DEVICE_ID",
 "error": "bad-device"}

A similar error and message is returned for invalid account_id or an account_id which is not associted with the user.

{"message": "no account with account ID: ACCOUNT_ID",
 "error": "bad-account"}

Repeating a request

If a user requests a device or account to be deactivated or reactivated when it already exists in that state, a message will be returned in the HTTP response body, informing the user that the requested device_id or account_id is already in the requested state:

HTTP/1.1 200 OK
{"message": "deactivation is already set to True for account: ACCOUNT_ID "}

A similar message is shown in the event of a repeated request for device deactivation and reactivation and account reactivation.

Requesting data for a deactivated account or device

If a user requests data from an account or device which has been deactivated, it will an HTTP 403:

{"message": "The requested account has been deactivated",
 "error": "deactivated-account"}

Again, a similar message is given in the event of requesting data from a deactivated account.


Status and scheduled maintenance information

The support engineers maintain a status page which records a list of all scheduled maintenance windows, along with updates on incidents as they occur. It is possible for clients to subscribe to automated email updates from this system.

Reporting issues to the support team

When encountering issues with the API, it can speed resolution if the support team are informed of the X-RI-Build HTTP header received in the problem response. Whilst all API requests appear to be directed at the same URI , this URI redirects traffic to a number of different server clusters depending on the client key and request type.

The X-RI-Build HTTP header looks like this:

X-RI-Build: 1.0-pre-ios9-395-g126226b; nj-api-7

When triaging issue reports, the support engineers will invariably ask for the curl commands that can be used to demonstrate replication of the issue, and for the server's response.

The feed returns a message: "Contact for access to this data"

This message will be returned when the demonstration key is used. Please contact us for a trial key with access to more data. If you already have a trial key, are you correctly specifying it in your client implementation?

I'm trying to pull an app's database file by file_id but I'm not getting any data back

file_ids are derived from an SHA-1 hash of the file's path and name, so they are constant for any given file. If the file's attributes or content change, it won't affect the hash.

However, sometimes app authors change the name of the file they store data in (and sometimes Apple do in new iOS releases). That's why, for instance, there several different file_ids to examine when getting WhatsApp data. These file_ids could be changed any time an app is updated.

It is recommended users pull JSON feeds instead of working with files and manipulating them directly. Using the feeds, one needn't worry over the efficacy of SQL, PList parsing or undeletion, and the feeds are quicker and much simpler to work with.

I am receiving rate-limiting errors from the server

The API rate-limits requests over a 15 minute window, and this limiting is configured per key. Most keys are rate-limited for security purposes.

API clients are returned data on their usage against limits in the HTTP header responses that they receive. These responses use the following headers:

  • X-Rate-Limit-Limit The number of requests permitted in a 15 minute window.
  • X-Rate-Limit-Remaining The number of requests remaining in the current window's allocation.
  • X-Rate-Limit-Reset The time remaining until the current rate-limit window ends, in milliseconds.

Here's an example set of live headers from a key on a 1,000 request rate-limit.

X-Rate-Limit-Remaining: 995
X-Rate-Limit-Limit: 1000
X-Rate-Limit-Reset: 3546.3297081

If the rate-limit is hit, the server will respond with:


The server will include the three rate-limit headers in this response.

The correct client behaviour is to wait for the duration specified by X-Rate-Limit-Reset to pass, at which point X-Rate-Limit-Remaining will be reset.

I'm received an email about remote access to the iCloud account I accessed

Polling the live feed modules (as noted above in the sample feed module flags section) can trigger an email being sent to the address associated with that iCloud account. Note that this only occurs for the live feed modules. Polling the point-in-time modules avoids the chance of email.

Need more functionality?

Reincubate's vision is to provide data access, extraction and recovery technology for all app platforms, be they mobile, desktop, web, appliance or in-vehicle.

The company was founded in 2008 and was first to market with both iOS and iCloud data extraction technology. With over half a decade's experience helping law enforcement and security organisations access iOS data, Reincubate has licensed software to government, child protection and corporate clients around the world.

The company can help users with:

  • iCloud access and data recovery
  • Recovery of data deleted from SQLite databases
  • Bulk iOS data recovery
  • Forensic examination of iOS data
  • Passcode, password, keybag and keychain analysis
  • Custom iOS app data extraction
  • Advanced PList, TypedStream and Mbdb manipulation

Contact the enterprise team for more information, or see

Terms & license

Users must not use the API in any way that is unlawful, illegal, fraudulent or harmful; or in connection with any unlawful, illegal, fraudulent or harmful purpose or activity. Full terms are available from the enterprise team.

billing support-icons-minus other support-icons-plus popular started

How can we help?

Our support team are here to help!

Our office hours are Monday to Friday, 9am to 5pm GMT. Currently it is .
We aim to reply to all messages within one working day.

Contact the enterprise team › Contact Team