BrowserState.db last_viewed_time? (Again)
Ian Whiffin
Posted: 2nd July 2024
Revised: 2024-09-09

In the last few weeks, there’s been a few more examiners reach out about this. There's clearly still some confusion so I thought I should do a brief update to clarify. 

As I previously stated, the BrowserState last_viewed_time is the time the tab took focus. The URL and Title shown in the database are related to the most recent page visited in that tab. 

There are differences between iOS versions that determine when the record is written but the meaning of the timestamp appears consistent. 

Testing iOS14 & Below

iOS 12, 13, 14 all create the BrowserState record immediately when a tab is created continuously update the URL and Title fields as navigation occurs. The timestamp is updated when the tab is given or loses focus.

To test this:

I opened a tab at 9:21 and searched for “9:21“. The BrowserState record was immediately created. The timestamp and URL/Title both showed 9:21: 

At 9:22, I searched for “922” and checked the database again.


You can see that the title is updated but the last_viewed_time remains 9:21.

I then completely closed Safari, reopening it at 9:23 and searched for “923”. Checking the database showed the updated timestamp and title:


Closing the tab and checking the database again showed no change to the data at all.

 

Testing iOS15 & Above

In iOS 15, 16, 17 and the 18 Beta, the record is not made in the BrowserState database immediately,  and therefore never has to be updated. It appears everything is stored in RAM and only written to database when the tab is closed. Again though, the last_viewed_time is the time the tab took focus.
 
I created a tab at 10:23 and searched for “1023”. Checking the database, there was no record.


At 10:24, I closed the tab and rechecked the database.


At 1025 I created a new tab and searched for “1025”.

At 1026, I used the same tab to search for “1026”.

I then closed the tab and checked the database.

As you can see, the last_viewed_time still reflects the time the tab was focused and the URL and Title are the related to the most recent page visited.

 

Tab Focus?

Tab Focus can occur for a few different reasons;

  1. The tab is created and therefore takes focus.
  2. Safari is closed (not backgrounded) and reopened. The reopening causes the tab to take focus.
  3. Switching between tabs. The tab being brought INTO view takes focus. The tab being moved OUT of view is updated (but this will only be reflected if the tab is closed without ever receiving focus again)
  4. Closing a tab - Big BUT here. The tab being closed is NOT updated. But, the process of closing one tab causes another tab to take focus and therefore the tab receiving focus is updated.

 

Scenarios

This can cause some interesting scenarios that it’s worth looking at individually.

Scenario 1
Imagine I open a tab at 10am and search for “1000”. The last_viewed_time inherits the time the tabs took focus (in this case, when the tab was created), so, 10am. 
I then minimize safari for 1 hour, reopening it at 11am. Minimize/Maximize doesn’t affect the focus, so no timestamps are updated. 
I can close the tab, and the record will show a last_viewed_time of 10am and a search of “1000”, making it appear accurate. 

Scenario 2
Similar setup to before. Open a tab at 10am and search for “1000”. I then CLOSE safari, and OPEN it an hour later. 
Opening Safari from a closed state DOES update the timestamp. So the timestamp now reads 11am. I close the tab and the record is written with a timestamp of 11am and a search term of “1000”. This is clearly not accurate and makes it appear the search for “1000” was conducted at 11am. 

Scenario 3
Keeping the same setup still, tab opened at 10am and searched for “1000”. 
This time, I keep safari open for the next hour and run a new search every minute. So I have a search at 10:01 for “1001”, a search at 10:02 for “1002” and so on. 
At 11:00 I do my final search for “1100” and close the tab. 
Throughout the hour, the same tab has been in focus and so the timestamp was never updated. 
The record in the database will show a last_viewed_time of 10am and the most recent URL visited of “1100”. This is also not accurate and makes it appear that I searched for “1100” at 10am. 

Scenario 4
Finally, sticking with the same premise, I open a tab at 10am and search for “1000”. I MINIMIZE Safari for the hour. At 11am I MAXIMIZE Safari and search for “1100”. Again, since minimize/maximize doesn’t cause a refocus to occur, the last_viewed_time remains 10am but the URL shows the most recent value of “1100”. This has the same result as Scenario 3 and makes it appear I searched for “1100” at 10am. 

 

Timeline

I'll also present the data in a timeline which I hope will add further clarity. This table attempts to show the state of the last_viewed_time, URL and Title as they exist in memory and/or database (depending on iOS version).

Time Action Tab Focus Event Navigation Event Result
10:00 Open a tab.
Search for "1000".
Yes Yes

last_viewed_time: 10:00
URL : Relates to "1000" search
Title : "1000"

This can easily be mistaken as a correlation between the last_viewed_time and the URL. But it is just a coincidence.

10:05 Search "1005" in same tab. No Yes

last_viewed_time: 10:00
URL : Relates to "1005" search
Title : "1005"

This could be mistaken as the "1005" search occured at 10:00.

10:10 Minimize Safari No No

last_viewed_time: 10:00
URL : Relates to "1005" search
Title : "1005"

No change.

10:15 Maximize Safari No No

last_viewed_time: 10:00
URL : Relates to "1005" search
Title : "1005"

No change.

10:20 Search for "1020" No Yes

last_viewed_time: 10:00
URL : Relates to "1020" search
Title : "1020"

This could be mistaken as the "1020" search occuring at 10:00.

10:25 Close Safari No No

last_viewed_time: 10:00
URL : Relates to "1020" search
Title : "1020"

No change.

10:30 Open Safari Yes No

last_viewed_time: 10:30
URL : Relates to "1020" search
Title : "1020"

This could be mistaken as the "1020" search occuring at 10:30.

10:35 Open new tab (Tab 2)
Search for "1035"
Yes Yes

last_viewed_time: 10:30
URL : Relates to "1020" search
Title : "1020"

last_viewed_time: 10:35
URL : Relates to "1035" search
Title : "1035"

A new Tab is created but the original tab is unaffected.

10:40 Close Tab 2
This causes Tab 1 comes back into focus.
Yes No

last_viewed_time: 10:40
URL : Relates to "1020" search
Title : "1020"

The original tab's last_viewed_time is updated which could be mistaken for the "1020" search occuring at 10:40.

10:45 Search for "1045" No Yes

last_viewed_time: 10:40
URL : Relates to "1045" search
Title : "1045"

This could be mistaken as the "1045" search occuring at 10:40.

Hopefully, the above scenarios and table demonstrates that there are occasions where;

  • The last_viewed_time is NEWER than the contents of the URL and Title field (as is the case at 10:30 and 10:40).
  • The last_viewed_time is OLDER than the contents of the URL and Title field (as is the case at 10:05, 10:20 and 10:45).

Essentially, the last_viewed_time value could be before or after the actual time of the URL visit. Making this timestamp utterly unreliable.

Wrapping Up

The nice thing about this artifact is that it’s super easy to test for yourself. BrowserState.db is included within an Encrypted iTunes Backup so you don’t even need an advanced extraction tool.

 

Previous Article
"Apple Maps - Visited Location?"
Next Article
"Sync Peers"
Search
Social