Accessing iPhone Call History
Posted: August 19, 2011 Filed under: Tutorial | Tags: call, call_history.db, history, ios, iphone, log, NSDirectoryEnumerator, NSFileManager, objective-c, sqlite, xcode 105 CommentsAlthough there is no API in the SDK to access iPhone’s Call History, there is a read-only SQLite database that gives access to the call history. In this tutorial, we shall learn what is the name of this database; where is it stored; what is its schema; and finally how can we access it?
Call History Database – Path, and Schema
The iPhone call history is stored in “call_history.db” which is located at the following path:
/private/var/root/Library/CallHistory/call_history.db
There are other important databases on the iPhone, some of which are accessible and some are not. We can find that out using the following piece of code. This basically enumerates the system folder and subfolders and finds databases that are readable:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDirectoryEnumerator *dirnum = [[NSFileManager defaultManager] enumeratorAtPath: @"/private/"];
NSString *nextItem = [NSString string];
while( (nextItem = [dirnum nextObject])) {
if ([[nextItem pathExtension] isEqualToString: @"db"] ||
[[nextItem pathExtension] isEqualToString: @"sqlitedb"]) {
if ([fileManager isReadableFileAtPath:nextItem]) {
NSLog(@"%@", nextItem);
}
}
}
I got the following results:
var/db/launchd.db
var/mobile/Library/AddressBook/AddressBook.sqlitedb
var/mobile/Library/AddressBook/AddressBookImages.sqlitedb
var/wireless/Library/CallHistory/call_history.db
Feel free to share yours 🙂
So now we have the database path and we can easily read the values stored in it, but to know what value is what we need to know the schema. Here is a snippet to find that out:
NSString *callHisoryDatabasePath = @"/private/var/wireless/Library/CallHistory/call_history.db";
BOOL callHistoryFileExist = FALSE;
callHistoryFileExist = [fileManager fileExistsAtPath:callHisoryDatabasePath];
[fileManager release];
if(callHistoryFileExist) {
if ([fileManager isReadableFileAtPath:callHisoryDatabasePath]) {
sqlite3 *database;
if(sqlite3_open([callHisoryDatabasePath UTF8String], &database) == SQLITE_OK) {
//Getting table names and schema
sqlite3_stmt *compiledStatement;
NSString *sqlStatement = [NSString stringWithString:
@"SELECT * FROM sqlite_master WHERE type='table';"];
int errorCode = sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1,
&compiledStatement, NULL);
if( errorCode == SQLITE_OK) {
int count = 1;
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
int numberOfColumns = sqlite3_column_count(compiledStatement);
NSString *data;
NSString *columnName;
for (int i = 0; i < numberOfColumns; i++) {
columnName = [[NSString alloc] initWithUTF8String:
(char *)sqlite3_column_name(compiledStatement, i)];
data = [[NSString alloc] initWithUTF8String:
(char *)sqlite3_column_text(compiledStatement, i)];
NSLog(@"%@ : %@", columnName, data);
[columnName release];
[data release];
}
count++;
}
}
else {
NSLog(@"Failed to retrieve table");
NSLog(@"Error Code: %d", errorCode);
}
sqlite3_finalize(compiledStatement);
}
}
}
You will get something like this:
type : table
name : _SqliteDatabaseProperties
tbl_name : _SqliteDatabaseProperties
rootpage : 2
sql : CREATE TABLE _SqliteDatabaseProperties (key TEXT, value TEXT, UNIQUE(key))
type : table
name : call
tbl_name : call
rootpage : 4
sql : CREATE TABLE call (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, address TEXT, date INTEGER, duration INTEGER, flags INTEGER, id INTEGER, name TEXT, country_code TEXT)
type : table
name : sqlite_sequence
tbl_name : sqlite_sequence
rootpage : 5
sql : CREATE TABLE sqlite_sequence(name,seq)
type : table
name : data
tbl_name : data
rootpage : 6
sql : CREATE TABLE data (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, pdp_ip INTEGER, bytes_rcvd REAL, bytes_sent REAL, bytes_last_rcvd REAL, bytes_last_sent REAL, bytes_lifetime_rcvd REAL, bytes_lifetime_sent REAL)
More info on other iphone databases can be found on this link:
http://damon.durandfamily.org/archives/000487.html
Accessing the Call History
Now that we know the call history db path and schema, we can see that we are interested in the “call” table. Thanks to the above link, we know what exactly is stored in this table:
ROWID (INTEGER PRIMARY KEY AUTOINCREMENT) : Auto-incrementing field/counter
address (TEXT) : International-formatted foreign address
date (INTEGER) : OSX-epoch based datetime, convertable via date -r
duration (INTEGER) : Length of call in seconds rounded to next minute, 0 = missed call
flags (INTEGER) : Flags controlling the type of record; 5 – Outgoing call | 4 – Incoming call
id (INTEGER) : AddressBook ID for outgoing calls selected from AddressBook, otherwise -1
Now we should write some code to access that. The following code accesses the “call” table and stores the retrieved values in an array of dictionaries. You could write your own class and use an array of objects of that class:
NSString *callHisoryDatabasePath = @"/private/var/wireless/Library/CallHistory/call_history.db";
BOOL callHistoryFileExist = FALSE;
callHistoryFileExist = [fileManager fileExistsAtPath:callHisoryDatabasePath];
[fileManager release];
NSMutableArray *callHistory = [[NSMutableArray alloc] init];
if(callHistoryFileExist) {
if ([fileManager isReadableFileAtPath:callHisoryDatabasePath]) {
sqlite3 *database;
if(sqlite3_open([callHisoryDatabasePath UTF8String], &database) == SQLITE_OK) {
sqlite3_stmt *compiledStatement;
NSString *sqlStatement = [NSString stringWithString:@"SELECT * FROM call;"];
int errorCode = sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1,
&compiledStatement, NULL);
if( errorCode == SQLITE_OK) {
int count = 1;
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSMutableDictionary *callHistoryItem = [[NSMutableDictionary alloc] init];
int numberOfColumns = sqlite3_column_count(compiledStatement);
NSString *data;
NSString *columnName;
for (int i = 0; i < numberOfColumns; i++) {
columnName = [[NSString alloc] initWithUTF8String:
(char *)sqlite3_column_name(compiledStatement, i)];
data = [[NSString alloc] initWithUTF8String:
(char *)sqlite3_column_text(compiledStatement, i)];
[callHistoryItem setObject:data forKey:columnName];
[columnName release];
[data release];
}
[callHistory addObject:callHistoryItem];
[callHistoryItem release];
count++;
}
}
else {
NSLog(@"Failed to retrieve table");
NSLog(@"Error Code: %d", errorCode);
}
sqlite3_finalize(compiledStatement);
}
}
}
If you want to show date as a real date not number of seconds since epoch use this if-statement:
if (![columnName isEqualToString:@"date"]) {
[callHistoryItem setObject:data forKey:columnName];
}
else {
NSDate *callDate = [NSDate dateWithTimeIntervalSince1970:[data intValue]];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterFullStyle];
[dateFormatter setTimeStyle:NSDateFormatterFullStyle];
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
[callHistoryItem setObject:[dateFormatter stringFromDate:callDate] forKey:columnName];
}
Other conditions can be added to check the ‘flag’ and determining whether the call is incoming or outgoing.
Dont be afraid of using this in an application for the app store. There is already an app on iTunes that accesses call history.
Note: I found values other than 4 and 5 for flags, like 20,21. I dont know what they mean yet. Ill update as soon as I do. Meanwhile, you guys share what different values you get with us and also if you find out what they mean.
Happy Coding 🙂
Hi ,
I am getting following 3 paths
var/db/launchd.db
var/mobile/Library/AddressBook/AddressBook.sqlitedb
var/mobile/Library/AddressBook/AddressBookImages.sqlitedb
but not getting following path using your code.
var/wireless/Library/CallHistory/call_history.db.
Is there any way to get above path permission to access call log history.
please reply with solutions
Hi Shankar,
I think this has to do with os version. Have a look at this link:
http://stackoverflow.com/questions/5498291/iphone-unable-to-open-database-file-for-call-history-db-in-xcode-app
What os are you running???
Yes it is working for ios 4.0. This blog is really useful for me. Thanks a lot for your reply & providing solution to access call logs.
Glad I could help 🙂
Thanks for sharing this,
The problem is that dosnt work with iOS 5
I’d gladly pay $4.99 for a simple app that stores my entire call history in a searchable file somewhere on the iphone. I see lots of ways to back up call history to my desktop, but that’s not nearly as useful.
Storage could be local on the phone or to a cloud service as an xls file, though the local would be preferable.
The “100 entries only” limit on the native phone history/call app is just absurd. Apple gave me room for 10,000 songs but only 100 2byte log entries? I’m so surprised someone hasn’t solved this yet. (Did I miss a solution that doesn’t require jailbreaking my phone?)
Thanks!
(Post needed to get notifications)
There is a link to an app that stores your call history….its on the app store meaning you dnt need to jailbreak your phone to get it. But its not 4.99 its 9.99 😉
i can access database of call history.db in jailbreak but i can’t access database in actual device.how can i access data in purchase iPhone 4s?..please help me..
This is really helpful. Thank you for sharing that =)
Maybe a stupied question, but how do you know which hidden APIs that you are allowed to use and will pass signing? Is it trial and error?
No. its not. Its not a hidden API. Its just a db that wasnt accessible prior to iOS4.0. Plus i gave a link to an app that does this and its on the app store (obviously went through the Apple Review process). This code will work on non-jailbreak devices which is also an evidence that its Apple approved.
Hi Bushra,
I left a message for you in linkedin. I totally love this blog and I learnt a lot of stuff from this blog. Kindly email me at tabtrend at gmail.com . I have a ios project and need your help.
– Arun
Hey,
Does somebody knows if those files will be accessible on iOS 5?
This seems like a bigger security/privacy issue than the famous localization database issue!
Thanks.
Kevin
iOS 5 is under nda. Even if i find out, i couldnt tell you and i would also advice others not to comment on this. But ill post an update as soon as iOS 5 launches 🙂
Ok. So as an iOS developer you have the new iOS5 and you have probably tried accessing the database. I understand that you are under an NDA and can’t discuss details, so I will wait until it’s officially released. Until that time, should I be worried that this will no longer work?
I think not because although this feature can be misused there are no instances of that as yet
Ok. I wasn’t too worried that under iOS5 that the database would be inaccessible, but now I can’t find it.
I’m starting to worry.
Any tips on how I can get this to go under ios5?
every thing is fine, how to apply this in my own app , what are the IB elements to be taken……?????
can you please help me…..
I have shared the main code to start anyone off….unfortunately i cant write ur app for you 🙂
sir, thankyou for your reply response,, and where to apply this code is my question ,, i mean that , do i need to create a DataBase named “callhistory”
in my terminal (or wat to do) ??
how to apply this code in app,( in viewDidLoad method )??? or some wher else??
its ma’am, keshav this code is ready to go anyhwhere you like. This code is complete in the sense of accessing the data, how you display it or whether you decide to store it inside your app is totally dependent on you 🙂
my task is to access the callLogs(missed,dailed,recieved) into my app, to find out the count of all the Call Logs and to display in my app,,, ,,,
sir , do i need to create database named (callhistory)or what?
thanks for your replies…..
can you please help me ?????
Thanks very much for this! I look forward to your update post after iOS5 is released. I’d love to use this approach in an application I’m building that needs access to the call log, but I’m leery that iOS5 will render this approach unusable.
var/db/launchd.db
var/mobile/Library/AddressBook/AddressBook.sqlitedb
var/mobile/Library/AddressBook/AddressBookImages.sqlitedb
var/wireless/Library/CallHistory/call_history.db
You got this list by running the script in your iphone device ? I tried it in the simulator and i got different output.
yeah on iphone…..simulator doesnt have a call history 😐 what else did u expect???
I just tried this with IOS5 and i cant see call_history.db anymore. I can only see launchd.db
Anyone have a solution for iOS 5.0?
Sorry forgot to tick notification boxes
this is great!!!!
very well explained
thanks a lot man
Did you get it working on OS 5.0?
It wont work on 5.0 because call_history.db is not accessible anymore
i get values other than 5 & 4 in “flags filed. it is 65540 & 65541. Wonder if they has sth to do with 65536 which is 2^16?
These are bitfields.
00004 = 00000000000000100
00005 = 00000000000000101
65540 = 10000000000000100
65541 = 10000000000000101
So you only have to check the bit0 to determine wether it is incoming or outgoing.
But do you still use 4.3 or could you manage to read these values on iOS5? How?
Hi koverg,
can you please tell me what is the memory location of this value i.e
where are these values stored? please reply
Hope sooner or later they release a way to access recent calls.
Hi,
I want to know that how many calls log data is stored in call_history.db table OR how many days back data is stored in call_history.db?. Is there any limitations for call_history.db table to store the call logs? If have please help me regarding to know call_history.db limitations.
Waiting for your valuable reply.
Thanks.
It has all the data that is shown in the Phone app i.e. if user deletes a record or clears the list in the Phone app then the records are also removed from this db.
Hi,
Thanks for your valuable reply. This is helped me a lot to take some decisions.
Thanks a lot.
Hi Guys,
Is there is any possible to set reminder programatically…? Also I want to know is it possible to set ringtones programatically in non-jail broken devices…?
Thanks,
Ram
Although its totally irrelavent here but no to both of your questions, unfortunately!
I knew it is totally irrelavent, I hope I may get better answer here… 🙂 no probs…
Hi Bushra
I have an app called calimits which is mainly deals with call history of the iphone.
My problem now is the stop reading the call log (history) iOS5.
Please Advice.
Regards,
Ziad
Unfortunately ziad the call_history db is not accessible anymore. I dnt know of a workaround yet but ill post if i do
Thank you so much for answering.
I’m still searching for help on that.
calimits.com
Regards,
Ziad
Hi,
I want to know is there any way by which i can differentiate between calls(Unanswered/Busy/attended) in iPhone. I’ve developed phone like module inside my app which allows user to call directly from the app without quitting(run on background) my app and when call ends, it take the user back to my app(on current view controller). what i want is, to know whether the call i made goes unanswered, busy or attended by the recipient. It’s very necessary for what i am trying to do. what’s your thought on it, is it possible? I’ve done extensive research on it’s possibility and failed to find anything relevant.
Thanks
Its very much possible. Try looking into core telephony framework. Youll find ur solution there 😉
Does iOS 5 block/deny access to *all* /var/mobile/ and /var/wireless/ databases? Or just Call_history.db? For example, can an iPhone app utilize/access the SMS.db or is this toast now as well?
Thank you.
Sms db? Not a chance
hello sir ,
this code for very use full .but i con’t show history data in table view call.
only show data in nslog . plz help me.
Hi Pawan can you help me in getting Call log
using this code and geting call histroy in table view cell
NSString *address;
NSString *userId;
NSString *name;
NSString *ROWID;
NSString *date;
NSString *country_code;
NSDictionary *objdict=[callHistory objectAtIndex:indexPath.row];
address=[objdict objectForKey:@”address”];
userId=[objdict objectForKey:@”id”];
name=[objdict objectForKey:@”name”];
ROWID=[objdict objectForKey:@”ROWID”];
date=[objdict objectForKey:@”date”];
country_code=[objdict objectForKey:@”country_code”];
int flag=[[objdict objectForKey:@”flags”]intValue];
if(flag==4)
{
//NSLog(@”call is incoming”);
//NSLog(@”call is incoming duration is: %@”,[callHistoryItem objectForKey:@”duration”]);
ObjCellHistoryview.CallImage.image=[UIImage imageNamed:@”b.png”];
}
else if(flag==5) {
//NSLog(@”call is outgoing”);
//NSLog(@”call is outgoing duration is: %@”,[callHistoryItem objectForKey:@”duration”]);
ObjCellHistoryview.CallImage.image=[UIImage imageNamed:@”o.png”];
}
int durations=[[objdict objectForKey:@”duration”]intValue];
if(durations==0)
{
//NSLog(@”call is Misscall”);
//NSLog(@”duration is: %@”,[objdict objectForKey:@”duration”]);
ObjCellHistoryview.LblDuration.text =[NSString stringWithFormat:@”%d”,durations];
ObjCellHistoryview.CallImage.image=[UIImage imageNamed:@”r.png”];
}
ObjCellHistoryview.LblHNo.text =[NSString stringWithFormat:@”%@%@”,name,address];
//ObjCellHistoryview.LblDuration.text =[NSString stringWithFormat:@”%@”,duration];
ObjCellHistoryview.LblHTM.text =[NSString stringWithFormat:@”%@”,date];
Thanks very much for this……….
Hi Sumit , can you help me for this getting call logs from iPhone DB , waiting for your replay my email address is gmaliwal777@gmail.com .
Thanks for this new info.
you post very helpful ,
But do you have any walk-around solution for iOS 5?
Unfortunately Adel, No I don’t.
Hi Guys,
I have to access callhistory.db in iOS 5 App for calimit App.Any clues.Plz share
hi this is outdated. now for ios 5 it not working. so tell new path for this. But that was nice.
The access has been blocked so there is no path for ios 5 😛
I understand that that is no way to access to the log in IO5 and there is no walk around. My question is: is there a way to get the total amount of sent and get byte transfer?. I can see that information in General – Usage – cellular Networking data Volume.
no..there must be smthing..check the app viber in appstore…This app shows the call history and it works fine in ios5….
viber shows the history of calls made through it not the actual phone history from phone app
i am newbee can you post code for me….
Calimits is the answer 😉
That app only works on iOS 4.x
I have iphone 3gs with ios5.0.1 upgraded and run your code
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDirectoryEnumerator *dirnum = [[NSFileManager defaultManager] enumeratorAtPath: @”/private/”];
NSString *nextItem = [NSString string];
while( (nextItem = [dirnum nextObject])) {
if ([[nextItem pathExtension] isEqualToString: @”db”] ||
[[nextItem pathExtension] isEqualToString: @”sqlitedb”]) {
if ([fileManager isReadableFileAtPath:nextItem]) {
NSLog(@”%@”, nextItem);
}
}
}
Output:
2012-04-30 18:11:50.377 CallClass_InMain[1993:707] var/MobileSoftwareUpdate/softwareupdate.232/target/root/System/Library/Frameworks/CoreLocation.framework/Support/factory.db
2012-04-30 18:11:50.423 CallClass_InMain[1993:707] var/MobileSoftwareUpdate/softwareupdate.232/target/root/System/Library/Frameworks/CoreTelephony.framework/Support/lasd.db
2012-04-30 18:11:50.431 CallClass_InMain[1993:707] var/MobileSoftwareUpdate/softwareupdate.232/target/root/System/Library/Frameworks/CoreTelephony.framework/Support/plmn.db
2012-04-30 18:11:55.961 CallClass_InMain[1993:707] var/db/launchd.db
2012-04-30 18:11:56.279 CallClass_InMain[1993:707] var/root/Library/Caches/Backup/cache.db
2012-04-30 18:11:56.295 CallClass_InMain[1993:707] var/root/Library/Caches/com.apple.backupd/Cache.db
2012-04-30 18:11:56.307 CallClass_InMain[1993:707] var/root/Library/Caches/com.apple.coreservices.appleid.agent/Cache.db
2012-04-30 18:11:56.350 CallClass_InMain[1993:707] var/root/Media/iTunes_Control/iTunes/MediaLibrary.sqlitedb
2012-04-30 18:11:56.362 CallClass_InMain[1993:707] var/root/Media/iTunes_Control/iTunes/UbiquitousMetadata.sqlitedb
Didn’t showing any call_history database.
var/mobile/Library/AddressBook/AddressBookImages.sqlitedb
var/wireless/Library/CallHistory/call_history.db
Please help where I am going wrong.
This db is no longer accessible in iOS 5.x
Just for reference, this database is also available in the iTunes backup of the phone. The name is 2b2b0084a1bc3a5ac8c27afdf14afb42c61a19ca.
[…] iOS Call History Tutorial Share this:FacebookTwitterLike this:LikeBe the first to like this. Leave a comment […]
How come these people are accessing it?
http://omegaspy.com/view/homepage.aspx?lang=en-US
This is a cydia application which only works on jailbroken phones.
and this too
http://www.mobile-spy.com/iphone.html
And this too
Hi is there a way to edit the call log. Iphone 3g 4.2.1
This should work for iOS 4.x
I do not even understand how I finished up right here, however I believed this put up was great. I don’t realize who you are but definitely you are going to a famous blogger in case you aren’t already. Cheers!
This sample code does not work for ios 6.0 please help
your iPhone might not be jail broken…
Fantastic site. A lot of helpful information here. I am sending
it to a few friends ans also sharing in delicious.
And of course, thank you to your effort!
I don’t get /private/var/db/callhistory/call_history.db in iOS 5.0 simulator . i am getting another DB’s log among them one is /private/var/db/launched.db . i am going to access thid using sqlite3 iPhone API then it returns me “Failed to retrieve table”
Your help is appreciated
Thanks & Regards
Ghanshyam Maliwal
Actually the access to that db has been blocked now
Hey Bushra, any update for ios6 ?
Still Out of our reach buddy
Thanks for reply buddy
Hello Xs2bush,
I can understand that the access may have been blocked now on call log db, but now when IOS5 and IOS6 supports background tasks and multitasking, can we listen the call events in application while app is running in background mode? Call may be initiated by user from the native calling app, and app should listen the call states while running as a background task and build our own database of call logs.
Could you please suggest something on that?
—
This is possible since this https://itunes.apple.com/us/app/navita-t.e.m.-personal/id590228620?mt=8 application does that, even in iOS 6. The question is, how?
This is possible since this https://itunes.apple.com/us/app/navita-t.e.m.-personal/id590228620?mt=8 application does that. The question is, how?
[…] website like “Accessing iPhone Call History” also says, it’s possible, how’s it […]
How about now in iOS 7 beta 2? 🙂
[…] to get call log details (Received, Dailed and missed) from NonJailbreakenIPhone? I follow this link https://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/ but i didn’t get any thing. If possible please provide some code or […]
[…] to get call log details (Received, Dailed and missed) from NonJailbreakenIPhone? I follow this link https://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/ but i didn’t get any thing. If possible please provide some code or […]
Does anyone know how they got access to call duration times?
https://itunes.apple.com/ca/app/navita-t.e.m.-personal/id590228620?mt=8
[…] Different vendor monopolies don’t let that happen. Famous debacle of 2010 between Google and Facebook over data usage resulted in loss of both sides’ users. Apple implies its core genes of protection has not made call history accessible and that can be accessed only through certain improvised methods. […]
[…] https://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/ […]
Hi Guys,
I am doing Call History Based application. But i unable to get the call log details. Still searching but no positive result. If you guys succeeded with call history app means , please help me . I am struggle to move next step in my app.
Tell me is it possible in iOS6 and iOS7 ?
I am looking forward your reply…..Please help me.
Thanks
Arunjack
Hi Gents,
Any updates for iOS 6.x ??
Any updates for iOS7?
[…] https://iosstuff.wordpress.com/2011/08/19/accessing-iphone-call-history/ […]
For iOS 7 or 8 ?Any other method?
i can access database of call in jailbreak but i can’t access database in actual can i access data in purchase iPhone 4s?..please help me.
afer the ios8,the callHistory is in private/var/mobile/Library/CallHistoryDB/CallHistory.storedata
is it possible to read data such as total number of sms sent for sms.db or any other source for a non jail break device? If so could you explain how this could be done, please?
Can we access the call_history.db file in iOS 9 ?
how to implement in swift of call history get