Privacy Browser

Privacy Browser 1.12

Privacy Browser 1.12 has a forward/backward history list. There are many websites (an example being that forward or redirect URLs within their domain, sometimes multiple times. When visiting these URLs, pressing back would go back to the redirect, which would then reload the current website. Sometimes this could be overcome by tapping back multiple times quickly, but the history list provides a more elegant solution. The “Clear History” button in the screenshot comes from the development version of Privacy Browser, and will be included in 1.13.


Long-pressing on a link now displays the target URL.


Long-pressing on an image gives options to view or download.


Find on Page allows for the searching of text on the current website.


Hartmut Kemmer, who discovered the CPU bug in Privacy Browser 1.10, requested that Privacy Browser be completely removed from RAM on “Clear and Exit”. By default, when an app is closed, Android keeps it in RAM but marks the space as available, effectively making it a cache of the state of the app when it closed. This allows the app to relaunch quickly if the user opens it again. Over time, if other apps request the memory it will be consumed. On “Clear and Exit”, an effort is made to delete all the sensitive information, like the current URL and the history list, but it is possible that something important could be remain. “Clear and Exit” now runs System.exit(0); as the last command, which entirely removes Privacy Browser from RAM.

“Back” and “Forward” are now disabled in the navigation list if they are not available, and the keyboard is automatically hidden when the navigation view opens.


A crash on displaying an SSL certificate error in Android KitKat and Lollipop was fixed, as well as a crash when failing to parse some Content-Disposition headers on file downloads. As usual, updated German translations were provided by Aaron Gerlach.

Privacy Browser 1.13 will continue the polishing of existing features and the implementation of basic functionality. Top on the list is full screen browsing mode.

Privacy Browser

Privacy Browser 1.11

Privacy Browser 1.11 was released a little before I anticipated because of a nasty bug in 1.10 descovered by a user, Hartmut Kemmer, that caused it to consume massive amount of CPU, even when running in the background. A line of sloppy code was causing the options menu to constantly be destroyed and regenerated. This would start as soon as Privacy Browser was launched and continue even if Privacy Browser was not visible on the screen, consuming up to the entire resources of one CPU core. Only if Privacy Browser were completely closed by selecting Clear and Exit or swiping it from the Overview screen would the CPU consumption stop. This had an obvious negative effect on battery life. Privacy Browser 1.11 was released the same day the but was reported. In the future, CPU utilization testing will be performed before each release.


With this release, the target API was bumped to 24, which enables multi-window support on Android >= 7.0 (Nougat). Unfortunately, this does not provide support for Samsung’s custom multi-window implementation. Doing so would require the inclusion of a proprietary Samsung library, which is unlikely to happen.


Beginning with 1.9 a German translation was added to Privacy Browser. During the 1.11 development cycle, it was discovered that the APK build process was creating duplicate image files for the Guide and About sections of the app. This was consuming an unneeded .5 MB of space in the generated .apk. Resolving the problem resulted in a package size for 1.11 that is 432 KB smaller than 1.10, even though the size of the code base has grown by 100 KB.


Several improvement were made to the file download dialog. Files with an unknown size were previously reported as being -9.54e-17 MB (-1 / 1048576). File names provided by web servers in the Content-Disposition header included all the fields listed in the header after the file name. And Privacy Browser would crash on download with a permission error on API <= 22 (<= 5.1.1, Lollipop). All these issues were resolved in 1.11, although there isn’t much I can do to compensate for some of the silly names servers give files.


Web pages can now be printed using Android’s build-in printing framework.


The next release of Privacy Browser will continue the polishing of existing features and the addition of basic functionality. The top of the list is the ability to search for a term on a web page.

Privacy Browser

Privacy Browser 1.10

Privacy Browser 1.10 includes proxy integration with Orbot, which is a much requested feature. When the proxy is enabled, the app bar background turns light blue.


Enabling Orbot proxy support proxies all web requests through localhost port 8118. If someone has a need to proxy to a different IP address or port please let me know. That could be added if there were a use case where it was valuable.

There have been some improvements to the downloading of files. Previously, many files were downloaded as “downloadfile.bin”. Privacy Browser is now much better at guessing the file name. It also displays an alert dialog that allows the user to change the name before the download begins.


Downloaded files are now saved under /sdcard/Android/data/com.stoutner.privacybrowser.standard/files, which is accessible by other programs. In the future, downloads will default to /sdcard/Download, and the path will be user selectable, but doing so requires the WRITE_EXTERNAL_STORAGE permission, which I am not yet prepared to add.

There is now an option to display up to three additional action buttons in the app bar, space allowing. These buttons control first-party cookies, DOM storage, and form data. There is a bug in Android that causes the available space to be calculated when the app is started, but not updated on rotate.

Action Buttons

This release also contains a Do Not Track option described in detail in an earlier post, user agents for iOS and OS X, two additional search engines, and updated German translations provided by Aaron Gerlach.

The most requested feature that is not yet implemented is an integrated ad blocker. This is on the list of planned features, but it will likely be fairly time-consuming to implement. I would anticipate Privacy Browser will include an ad blocker sometime in the next six months.

The next release of Privacy Browser will likely contain a bunch of small fixes that provide polish to the browser and are easy to implement.

Privacy Browser

Do Not Track

Privacy Browser 1.10 will include an implementation of the DNT (Do Not Track) header. Because the implementation is not perfect, I felt it deserved a separate post.

DNT Is Useless

Although I believe the intentions of those who developed DNT were good, it does not provide any real additional privacy to users. This is because web servers get to choose if they want to voluntarily comply with the DNT request, and almost none of them do. The only organizations that do comply with DNT were those that already respected the users’ privacy and weren’t going to do anything inappropriate with user data anyway.

Imperfect Implementation

DNT suffers from all the difficulties of implementation imposed by Android’s WebView that were described in the post about the “X-Requested-With” header. Specifically, the DNT header is only sent with the initial URL request, and not with resource requests.

Browser Fingerprinting

In addition to the initial request only quirk, WebView also converts all header fields to lowercase letters. The spec for DNT is that the header should be “DNT:1”, which is how most browsers send it. Android’s WebView converts that to “dnt:1”. Web servers recognize this as a valid DNT header because header fields are technically case insensitive, but because only browsers that use WebView, like Lightning, send the DNT header in this form, it is one additional piece of information that web servers can use to fingerprint the browser.

Enabled By Default

Despite everything described above, I have decided that Privacy Browser 1.10 will ship with DNT enabled by default. This is because many privacy conscious users expect DNT, even though all it amounts to is privacy theater. If DNT were disabled by default I would spend half my development time responding to concerns from users. And the browser fingerprinting problem, though real, is so far down the list of possible ways to fingerprint the browser that I would be surprised if web servers bothered with it until we get to the point that we have tightened down all the easier mechanisms.

For those who don’t want it, DNT is easy to disable in the settings.

Update: With the release of Privacy Browser 1.14, DNT has been disabled by default.

Privacy Browser

Security and Privacy Canary

A new section of the website has been added that contains an annual security and privacy canary statement. Privacy Browser is not yet at a stage where a canary statement is necessary, but if it becomes successful, and is used by as many people as I expect it will be, there will come a point where it will be a target for government agencies. By definition, canary statements are only useful if you start publishing them before you need them, so I thought it smart to begin the practice now.

New canary statements will be published in January of each year.

Privacy Browser

Privacy Browser 1.9 and 1.9.1

Privacy Browser 1.9 and 1.9.1 have been released. Version 1.9.1 fixes a small problem that caused 1.9 to fail to build on F-Droid.

Privacy Browser 1.9 includes a German translation provided by Aaron Gerlach. Maintaining a translation requires a lot of work and I am grateful to Aaron for his contributions.

Privacy Browser 1.9 also includes a number of new features. Basic SSL handling is included. Tapping on the favorite icon will display SSL certificate information. SSL error messages are also presented to the user, which allows them to access sites that use self-signed SSL certificates or otherwise produce SSL errors. The SSL certificate information provided by Android’s WebView is more limited than I would like. Specifically, it does not expose the serial number or the SHA1 digest of the certificate. One of the planned features is to allow users to pin SSL certificates, which can be done with knowing the serial number or digest, but is not as secure.

Font size control has also been added. WebView has three settings for controlling font size: minimum font size, default font size, and text zoom. Text zoom seemed to be the easiest of the controls to present to the user. It is expressed as a percentage. I decided use a pre-built selection list of percentage options instead of text entry box for the user to type a number because it is easier and faster to use a pre-built list. The list is populated with the following percentages: 50%, 75%, 100%, 125%, 150%, 175%, 200%. In my testing, these options provide all the variation I could imagine a user desiring. If someone would like additional values added to the list, or needs access to the minimum font size and default font size controls, feel free to contact me.

Privacy Browser now handles “mailto:” links on websites. A couple of bugs were also fixed that caused the browser to crash when working with bookmarks with no favorite icon and the navigation drawer to sometimes stop working after viewing a full-screen video. Progress was made regarding the “X-Requested-With” header, which was covered in more detail in a previous post.

The major feature I plan to implement for Privacy Browser 1.10 is proxy integration with Orbot.

Privacy Browser Security and Privacy Canary

August 2016 Security and Privacy Canary


During the previous year, Stoutner has received 0 requests from governments or organizations to insert backdoors into Privacy Browser.

During the previous year, Stoutner has inserted 0 backdoors into Privacy Browser.


During the previous year, Stoutner has received 0 requests from governments or organizations to weaken the privacy of Privacy Browser.

During the previous year, Stoutner has made 0 changes to weaken the privacy of Privacy Browser.

Legal Requests for Information

During the previous year, Stoutner has receive 0 legal requests for information from government law enforcement organizations. These requests sought information for a total of 0 individuals.

During the previous year, Stoutner provided information in response to 0 legal requests for information from government law enforcement organizations. These responses included information for a total of 0 individuals.

The types of information that Stoutner possesses and can disclose to legal requests from government law enforcement organizations are described in the privacy policy.

Privacy Browser

The “X-Requested-With” Header

As mentioned is several places on this website and in the app, there are some negative implications of using Android’s WebView to render web pages in Privacy Browser. The purpose of this post is to describe one of these downsides, explain the mitigations that are currently being taken, and lay out thoughts for a more permanent solution down the road.

The Background

When any app uses Android’s WebView to request a web page, WebView attaches an extra header, named “X-Requested-With”, with the app ID. “X-Requested-With” was designed to be used as a flag to mark AJAX (Asynchronous JavaScript and XML) requests. In that sense, WebView’s use of the field for a different purpose is an abuse of the standard and can cause problems for some web pages.

The Problem

One of the web tracking technologies that Privacy Browser is designed to mitigate is browser fingerprinting. Any piece of information the browser sends a web server that makes it stick out from the crowd increases the ability of the web server to uniquely fingerprint the browser. Including the app ID in the header, especially as long as Privacy Browser has a small market share, increases the chance that the total information sent to the server is unique.

For the Standard version of Privacy Browser the app ID is “com.stoutner.privacybrowser.standard”; the Free version is “com.stoutner.privacybrowser.standard”. The following is a log from that shows what information Privacy Browser <= 1.8 transmits to a web server (note that the User Agent has been changed from the default to “PrivacyBrowser/1.0”).

GET / HTTP/1.1||Connection:keep-alive|Cache-Control:max-age=0|Upgrade-Insecure-Requests:1|User-Agent:PrivacyBrowser/1.0|Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|Accept-Encoding:gzip, deflate|Accept-Language:en-US|X-Requested-With:com.stoutner.privacybrowser.standard

The Workaround

Google doesn’t want to make it easy to get rid of the “X-Requested-With” header. However, there is a mechanism for replacing header information. This doesn’t allow a program to stop sending the “X-Requested-With” header, but it does allow a program to replace the app ID with a null value. Beginning with Privacy Browser 1.9, the following information will be sent in the headers:

GET / HTTP/1.1||Connection:keep-alive|Upgrade-Insecure-Requests:1|User-Agent:PrivacyBrowser/1.0|x-requested-with:|Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|Accept-Encoding:gzip, deflate|Accept-Language:en-US

The Problems with the Workaround

The first problem with this workaround is that sending “X-Requested-With:” is not the same as not sending it at all. There are only going to be a few browsers that send “X-Requested-With:” as a header, so for fingerprinting purposes this workaround is only slightly better than including the app ID.

The second problem is that the technique for overwriting WebView’s headers only works on the initial request to a website. Any dependent requests for resources (like images, CSS files, JavaScript files, etc.) use the default headers. So even in Privacy Browser >= 1.9, the log of a request for a resource will be as follows:

GET /wp-content/themes/twentysixteen/style.css?ver=4.5.3 HTTP/1.1||Connection:keep-alive|Cache-Control:max-age=0|User-Agent:PrivacyBrowser/1.0|Accept:text/css,*/*;q=0.1|Referer:https%3a//|Accept-Encoding:gzip, deflate|Accept-Language:en-US|X-Requested-With:com.stoutner.privacybrowser.standard|If-None-Match:"10d4b-535f10e3fb580-gzip"|If-Modified-Since:Thu, 23 Jun 2016 12%3a18%3a46 GMT

This is a problem for every browser that uses Android’s WebView. For example, Lightning 4.3.3 behaves the same way as Privacy Browser >= 1.9: initial web requests include “X-Requested-With:” and resource requests include “X-Requested-With:acr.browser.lightning”.

The Long-Term Solution

There is a provision in WebView to bypass the default web loading functions by manually acquiring the information using HttpURLConnection and feeding it into WebView. This would allow the complete removal of the “X-Requested-With” header. However, making sure that all possible types of HTTP communication are handled correctly would be complex and the initial implementation would likely result in buggy behavior on some websites.

Another solution is to stop using Android’s WebView and embed a customized WebView in Privacy Browser. This would also allow for the complete removal of the “X-Requested-With” header, but would be a time consuming commitment to maintaining the custom WebView (both from a security and bug perspective).

Long term, it is likely that using a custom WebView will be the best solution for Privacy Browser. The plan is to implement all the privacy functions that are compatible with Android’s WebView (pick the low hanging fruit) and then do a detailed analysis of the best way to move beyond that point.

Privacy Browser

Privacy Browser 1.8

I have decided that I am going to make a regular habit of posting when a new version of Privacy Browser is released, detailing what users can expect from the new version and what I am working on for the subsequent release.

The main feature in Privacy Browser 1.8 is a bookmark implementation. This is a fairly robust implementation that allows for the creation of bookmarks, folders, and subfolders, reordering of bookmarks, moving of bookmarks between folders, and editing of bookmarks and folders.

For Privacy Browser 1.9, I intend to implement SSL certificate controls, as well as WebView font size controls, both of which are features that have been requested by users.

I have also received a request to hold off on implementing features that require the addition of dangerous permissions. For users on Android Marshmallow or newer (version >= 6.0, API >= 23), dangerous permissions are not an issue because they can choose to only enable those that are required for the features they want to use. But for those on older versions of Android, they do not have the option to disable individual permissions. Several planned feature will require the use of dangerous permissions, particularly READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE. The concern is that websites will be able to take advantage of 0-day flaws in WebView to abuse the user’s phone through the use of these permissions.

My thought is to implement all the planned features that don’t require dangerous permissions before implementing those that do. Hopefully, by that time more people will have devices that run at least Android 6.0. Privacy Browser 1.8 runs on Android KitKat (4.4, API 19) and newer. According to the July 2016 Android Dashboard, 78.5% of devices that access the Google Play Store are running Android 4.4 or newer. Of the group that can install Privacy Browser, only 16.9% (13.3 / 78.5) are running Android 6.0. I would like to see that number closer to 50% before implementing features with dangerous permissions.

Android Dashboard

Early adopters of Privacy Browser tend to be a more technologically savvy group and have more advanced hardware than the average Android user. The Google Play Store provides summary installation information that shows that 41.67% of current Privacy Browser installations and 33.33% of Privacy Browser Free installations are on devices running Android 6.0. These numbers only represent installations throught the Google Play Store, which doesn’t account for the few installations through the Amazon Marketplace or what I am assuming are the fairly large number of installations through F-Droid.

Privacy Browser

Privacy Browser 1.7

With the release of Privacy Browser 1.7, I felt it would be valuable to write a post explaining the motivation behind the design decisions and what is coming next.

Privacy Browser 1.7 marks the single largest number of changed lines in the code since version 1.0 was released. It began as a need to create a more thorough About section to accommodate attributions for contributions. This expanded into a Guide that explains the basic principles and functionality of Privacy Browser.

The minimum API was increased to 19 (Android KitKat 4.4 or higher) with this release due to security concerns with the embedded WebView in older versions of Android. I imagine that the majority of the users of Privacy Browser already use devices with API >= 19. F-Droid, where I would imagine the majority of users acquire Privacy Browser, does not collect statistics from users. Google Play’s statistics show that nobody who has downloaded Privacy Browser or Privacy Browser Free is running a device with API <= 18.

Privacy Browser 1.8 will likely include bookmarks, which is my wife’s single most anticipated feature. There will probably also be a few other features that are easy to implement as well.