This is going to be a small privacy tutorial on how to clear cache, cookies and history in all five major browsers - Internet Explorer, Chrome, Firefox, Opera and Safari. The techniques here work only on Windows operating system but it's not hard to transfer the techniques to other systems. The tutorial comes with Windows batch scripts for each browser. It also documents how to erase the nasty flash cookies that are browser independent.

I wrote these batch scripts for the Browserling startup that I am doing together with James Halliday. The problem was that the browsers had to be reset between consequent uses. The easiest way to solve it was to run a batch cleanup script after each browser.

Google Chrome

Chrome stores history, cookies, cache and bookmarks in various databases and directories in the per-user application data directory at C:\Users\<username>\AppData\Local\Google\Chrome\User Data. The easiest way to get rid of all this data is just to erase everything there. Chrome creates this directory anew if it finds it missing.

@echo off

set ChromeDir=C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data

del /q /s /f "%ChromeDir%"
rd /s /q "%ChromeDir%"

This simple batch script first deletes all files in %ChromeDir% directory via del command and then deletes the directory itself via rd command. The /q flag makes the del command quiet, the /s makes it delete files from all subdirectories, and /f forces it to delete read-only files, too. The /s flag to rd makes it delete all subdirectories and /q makes rd quiet.

Mozilla Firefox

Firefox stores cookies, cache and history in two places. The first is per-user appdata directory C:\Users\<username>\AppData\Local\Mozilla\Firefox\Profiles and the second place is roaming profile data directory C:\Users\<username>\AppData\Roaming\Mozilla\Firefox\Profiles. To get rid of all the private data, delete the local data directory and delete all sqlite databases from the roaming data directory.

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Mozilla\Firefox\Profiles

del /q /s /f "%DataDir%"
rd /s /q "%DataDir%"

for /d %%x in (C:\Users\%USERNAME%\AppData\Roaming\Mozilla\Firefox\Profiles\*) do del /q /s /f %%x\*sqlite

The for command loops over all profile directories and deletes all the sqlite databases. You can also delete the whole roaming data directory but I didn't because Firefox stores extensions there, and there are several I use for Browserling.


Opera also stores cookies, cache and history in two different locations - the user's application data directory C:\Users\<username>\AppData\Local\Opera\Opera and the user's roaming data directory C:\Users\<username>\AppData\Roaming\Opera\Opera. Just get rid of both directories and you're safe.

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Opera\Opera
set DataDir2=C:\Users\%USERNAME%\AppData\Roaming\Opera\Opera

del /q /s /f "%DataDir%"
rd /s /q "%DataDir%"

del /q /s /f "%DataDir2%"
rd /s /q "%DataDir2%"

Apple Safari

Safari also stores cookies, cache and history in two locations - the user's application data directory C:\Users\<username>\AppData\Local\Apple Computer\Safari and user's roaming data directory C:\Users\<username>\AppData\Roaming\Apple Computer\Safari

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Applec~1\Safari
set DataDir2=C:\Users\%USERNAME%\AppData\Roaming\Applec~1\Safari

del /q /s /f "%DataDir%\History"
rd /s /q "%DataDir%\History"

del /q /s /f "%DataDir%\Cache.db"
del /q /s /f "%DataDir%\WebpageIcons.db"

del /q /s /f "%DataDir2%"
rd /s /q "%DataDir2%"

Microsoft Internet Explorer

Internet Explorer is much more tricker. It stores history, cookies and cache all over the place, including registry. Here is the batch script that deletes all that data from all the places:

@echo off

set DataDir=C:\Users\%USERNAME%\AppData\Local\Microsoft\Intern~1

del /q /s /f "%DataDir%"
rd /s /q "%DataDir%"

set History=C:\Users\%USERNAME%\AppData\Local\Microsoft\Windows\History

del /q /s /f "%History%"
rd /s /q "%History%"

set IETemp=C:\Users\%USERNAME%\AppData\Local\Microsoft\Windows\Tempor~1

del /q /s /f "%IETemp%"
rd /s /q "%IETemp%"

set Cookies=C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Cookies

del /q /s /f "%Cookies%"
rd /s /q "%Cookies%"

C:\bin\regdelete.exe HKEY_CURRENT_USER "Software\Microsoft\Internet Explorer\TypedURLs"

Notice that the last command is regdelete.exe. It's a small win32 utility that I wrote in c++ that erases the IE history, because it stores it in registry.

Here is the regdelete.c program:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
// compile as: mingw32-g++ regdelete.c -o regdelete.exe -mwindows

#define eq(s1,s2) (strcmp((s1),(s2))==0)

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nCmdShow) 
    if (!cmdLine || !strlen(cmdLine)) {
        printf("Usage: regdel.exe <HKEY> <path to regkey> - be careful not to delete whole registry\n");
        return 1;

    int argc;
    LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);

    if (argc < 3) {
        printf("Usage: regdel.exe <HKEY> <path to regkey> - be careful not to delete whole registry\n");
        return 1;

    char **argv8 = (char **)malloc(sizeof(char *) * argc);
    for (int i = 0; i<argc; i++) {
        int len = wcslen(argv[i]);
        argv8[i] = (char *)malloc(sizeof(char)*(len+1));
        wcstombs(argv8[i], argv[i], len+1);

    HKEY hkey;
    if (eq(argv8[1], "HKEY_CLASSES_ROOT")) {
        hkey == HKEY_CLASSES_ROOT;
    else if (eq(argv8[1], "HKEY_CURRENT_CONFIG")) {
        hkey = HKEY_CURRENT_CONFIG;
    else if (eq(argv8[1], "HKEY_CURRENT_USER")) {
        hkey = HKEY_CURRENT_USER;
    else if (eq(argv8[1], "HKEY_LOCAL_MACHINE")) {
        hkey = HKEY_LOCAL_MACHINE;
    else if (eq(argv8[1], "HKEY_USERS")) {
        hkey = HKEY_USERS;
    else {
        printf("Unknown hkey\n");
        return 1;

    HKEY key;
    int status = RegOpenKeyEx(hkey, argv8[2], 0, KEY_ALL_ACCESS, &key);
    if (status != ERROR_SUCCESS) {
        printf("failed opening %s\n", argv8[2]);
        return 1;

    std::vector<std::string> vals;

    for (unsigned int i = 0; ; i++) {
        DWORD size = 1024;
        char val[size+1];
        DWORD type;
        status = RegEnumValue(key, i, val, &size, NULL, &type, NULL, NULL);
        if (status == ERROR_NO_MORE_ITEMS) break;
        if (status == ERROR_SUCCESS) {
        printf("failed enumerating %s\n", argv8[2]);
        return 1;

    typedef std::vector<std::string>::iterator vsi;
    for (vsi i = vals.begin(); i != vals.end(); i++) {
        status = RegDeleteValue(key, i->c_str());
        if (status != ERROR_SUCCESS) {
            printf("failed deleting %s\n", i->c_str());
            return 1;

    return 0;

Compile this source code via mingw or visual studio and you'll have the regdelete.exe program.

Flash Cookies

Flash cookies reside in C:\Users\<username>\AppData\Roaming\Macromedia\Flash Player\*. The easiest way is to get rid everything in there:

@echo off

set FlashCookies=C:\Users\%USERNAME%\AppData\Roaming\Macromedia\Flashp~1

del /q /s /f "%FlashCookies%"
rd /s /q "%FlashCookies%"

That's it. Have fun clearing that cache!

Hey guys, here are the lastest StackVM news. So we applied to Y Combinator for the Winter 2011 funding cycle but got rejected. On November 2 we got an email saying that they could not accept our application for funding, which meant that we wouldn't even get the interview. Our plan was to surprise Y Combinator folks at the interview by launching a private beta version of our software one day before the interview so that at the time we got interviewed the story was on the Hacker News front page. Well, now we can't surprise them this way, but we can surprise everyone else by saying that we are launching public beta!

Our first product is built on top of StackVM and is called Browserling. It's an interactive cross-browser testing tool inside of your browser. A real browser inside of your browser! Just go to to try it out! (please use Chrome.)

In case there is a long queue of people willing to try Browserling, we also made a short video that shows what it is and how it works:

Browserling is a freemium based product. If you register, you get 5 mins for free for as many times as you wish (but you have to wait in the queue again with everyone else). If you don't register, it's just 1min 30secs for as many times as you wish. We haven't figured out the paid plans yet, but we'll get there shortly.

As Browserling is beta, we currently provide Internet Explorer versions 5.5, 6, 7, 8, and 9, (version 5.5, 6, 7, 8 via IETester, and version 9 is native IE), Chrome, Firefox, Safari and Opera.

Browserling is also just the first of many projects that we'll be launching. The next one is going to bring arbitrary desktop applications to the web, and then we have a whole bunch more planned. All these projects will be based on the StackVM technology!

If you're interested in how all of this develops, please subscribe to my blog and follow me on Twitter!

Also, if you use IRC, join #stackvm channel on and have fun with us!

I wrote an awesome node.js module for use at StackVM - a module called node-lazy that does lazy list processing through events!

It comes really handy when you need to treat a stream of events like a list. The best use case currently is returning a lazy list from an asynchronous function, and having data pumped into it via events. In asynchronous programming you can't just return a regular list because you don't yet have data for it. The usual solution so far has been to provide a callback that gets called when the data is available. But doing it this way you lose the power of chaining functions and creating pipes, which leads to not that nice interfaces. (See the 2nd example below to see how it improved the interface in one of my modules.)

Check out this toy example:

var Lazy = require('lazy');

var lazy = new Lazy;
  .filter(function (item) {
    return item % 2 == 0
  .map(function (item) {
    return item*2;
  .join(function (xs) {

This code says that lazy is going to be a lazy list that filters even numbers, takes first five of them, then multiplies all of them by 2, and then calls the join function (think of join as in threads) on the final list.

And now you can emit data events with data in them at some point later,

[0,1,2,3,4,5,6,7,8,9,10].forEach(function (x) {
  lazy.emit('data', x);

The output will be produced by the join function, which will output the expected [0, 4, 8, 12, 16].

And here is a real-world example. Some time ago I wrote a hash database for node.js called node-supermarket (think of key-value store except greater). Now it had a similar interface as a list, you could .forEach on the stored elements, .filter them, etc. But being asynchronous in nature it lead to the following code, littered with callbacks and temporary lists:

var Store = require('supermarket');

var db = new Store({ filename : 'users.db', json : true });

var users_over_20 = [];
  function (user, meta) {
    // predicate function
    return meta.age > 20;
  function (err, user, meta) {
    // function that gets executed when predicate is true
    if (users_over_20.length < 5)
  function () {
    // done function, called when all records have been filtered

    // now do something with users_over_20

This code selects first five users who are over 20 years old and stores them in users_over_20.

But now we changed the node-supermarket interface to return lazy lists, and the code became:

var Store = require('supermarket');

var db = new Store({ filename : 'users.db', json : true });

db.filter(function (user, meta) {
    return meta.age > 20;
  .join(function (xs) {
    // xs contains the first 5 users who are over 20!

This is so much nicer!

If you wish to try node-lazy just do npm install lazy! Alternatively, if you don't have npm, you can git clone and set your NODE_PATH environment variable to point to that directory.

Enjoy and follow the future node-lazy developments in its github repo - node-lazy at github!

Article Sponsors


Want to sponsor my future (or past) articles? Contact me for prices and options!

I was interviewed recently on 2011-10-04 by Michael Matuzak from Lambdaphant. I copied the interview here in case Michael's website ever changes or goes down. (Update: Michael's website changed. Here is the original interview from the archive.).

This first interview is with Peter Krumins who runs the blog catonmat. Peter is also a founder along with James Halliday of StackVM.

How did you get started in programming?

I don't really know. All I remember is that I have always wanted to be a programmer. From the first day I learned about computer programming, whenever it was, I wanted to be a programmer. I didn't really get stared until I met this person on IRC in around 1996, who knew everything about computers and programming and he helped me a bunch with getting started with Unix and C programming.

I've read that you initially wrote an IRC client as a first project. What language was that in?

That was the first kind-of-a-big-project, not really the very first. I had messed around with various languages and written tens of toy programs before. So at that time I was doing mIRC scripting, messing with Eggdrop bots and decided to create my own IRC client. I first tried to write it in C++ and MFC but it was beyond me at that age but Visual Basic was really straight forward and I wrote a fully working IRC client pretty quickly.

What methods did you use to teach yourself knowing very little about programming?

I'd program by reading tons of source code of other programs. At that time I didn't have Internet access, so I'd carry a pack of floppies around with me and fill them with source code of various programs whenever I had access to Internet somewhere, and then compile and study them at home.

What advice would you give to kids interested in programming now?

My advice is to start programming in a language with light syntax. Like I remember I couldn't really understand the C++ syntax, with all the template and class stuff but mIRC scripting and Visual Basic at the same time was really straight forward. It was also important that I saw the results quickly, so I'd recommend kids to use a language that can create GUI really easily, perhaps I'd even recommend using the same Visual Basic and just creating all kinds of toy programs, like animated games, twitter clients, network chat programs and similar small programs.

Like most hackers you use many different languages. I'm sure you try and use the best tool for the job to get work done (unless you are purposefully using the wrong tool to learn), but let's imagine that you had to pick one language to use for the rest of your life. What would that be?

It would be Haskell because you can't get more functional than that and I love functional programming, it makes the code so elegant and keeps your mind busy trying to come up with the most beautiful abstractions.

Over the last couple of years your blog has become pretty popular. The great content is significant in making that happen. How did you go about gaining readers, and do you think the programming subreddit and HN were significant in gaining popularity?

Yes, the great content is absolutely the key. If you write about something passionately and thoroughly people will notice your blog and start following. So I knew from the first day that social media was the way to gain popularity. I'd submit all my posts to reddit, and later when Hacker News was created, I'd submit them there too, and also ask my friends to Stumble my posts and I'd submit them to delicious, and tell everyone on IRC, and post my articles to Linux and related forums. But even with all this effort after the first year of blogging I only had 1000 RSS subscribers, it took another year to get to 7000 and then another year to 12000.

James Halliday and yourself are working on a start-up called StackVM. What gave you the idea for StackVM? How long until users will see an official beta?

It was actually James's idea. He first created a working prototype in Haskell in January 2010, and then he showed it to me. At that time we both knew each other already and had talked about startups and ycombinator and I really enjoyed James's passion for functional programming. And then in March James offered to do a startup. I had actually wanted to do a startup since 2004 or 2005, when I remember telling my friends about Paul Graham and his startup essays but I hadn't met the right person. This was finally a great opportunity to do what I had dreamed about and so it all started. I am moving to Oakland to work together with James in a few weeks and after a few more weeks we'll have the official beta. We already have quite a powerful server for doing beta!

How are you liking start-up life?

It's not any different than the regular life so I love it.

Are you going to Start-up school this year? If so who are you most excited to see speak?

No, I am not going. It takes place in October 16 and I'll be in Bay Area only in early November.

What is your favorite music to hack away to?
No music actually required.

What is your favorite fiction book?

I don't have a favorite fiction book. I have been focusing on reading academic and scientific books. From these books I'd recommend The New Turing Omnibus, which contains 66 awesome lightweight articles on various fundamental computer science topics.

GitHub Social CodingRemember my previous article "I pushed 30 of my projects to GitHub?" Well, I just gathered 20 more projects that I had done (or did recently) and pushed them all to GitHub.

Quick note on GitHub - GitHub is the best invention ever for programmers. Nothing stimulates you more than pushing more and more projects to GitHub and seeing people forking them, following them, finding and fixing bugs for you. I wouldn't be doing so much coding if there wasn't GitHub.

If you like my projects, I'd love if you followed me on github! Oh, and also on twitter! Thank you!

Right, so here are the new projects:


This is a node.js module for recording HTML5 Theora/Ogg videos. It's written in C++ and is the first class citizen of node.js, meaning that it's fully asynchronous. It uses libtheora and libogg libraries for recording.

I wrote this module for my StackVM startup so that anyone could record virtual machine video screencasts. See StackVM demo video #1 at around 1min 23secs, where I demo this module in action.


This is another node.js module for producing PNG images from raw RGB/BGR/RGBA/BGRA buffers. It's also written in C++, is asynchronous, and uses libpng to produce images. I also wrote it for StackVM. I added a concept of stacked-pngs to the library where many virtual machine screen updates get stacked together to produce the final image, but that is a topic for a separate post.


This is also a node.js module for producing JPEG images from raw RGB buffers. It uses libjpeg (or libjpeg-turbo, which is much faster than libjpeg), it's is written in C++ and is asynchronous.

This module was also written for StackVM and it will be used in cases when the client has a really slow connection. In that case the virtual machine screen updates get downsampled to quality and size that the client is able to receive.


This is a module for node.js for producing GIF images. I like this module the most because it can be used to record what I call "gifcasts". Gifcasts are screencasts that get recorded to animated gifs. Here is an example gifcast that I recorded - A gifcast of me plurking from Windows XP.

This module is also written in C++ and uses giflib.


This is a module for node.js that unifies node-png, node-jpeg and node-gif. So instead of requiring all three modules, you just var Image = require('image') and then can do things like:

var png = Image.encodeSync('png', buffer); // or
var jpeg = Image.encodeSync('jpeg', buffer); // etc.
var gif = Image.encodeSync('gif', buffer);


Node-supermarket is like a regular key-value store (hash-table), except greater. It uses node-sqlite as the underlying storage engine that gives it unprecedented stability. This library doesn't end here. The plan is to create an object store, where you can just dump the whole js objects, and then restore them back, map, filter and fold on them, etc.


Supermarket-cart stores connect sessions in supermarket key-value store.


This ia a node.js module for doing base64 encoding/decoding. I wrote it because half a year ago when I started working on StackVM, node.js didn't have base64 encoding functions and all other modules were terribly broken for binary data. So I named this module "base64 module that actually works."


This is a HTTP proxy written in node.js. It has access control and URL black lists. I wrote it for fun.

Perl TCP Proxy

This is a TCP proxy written in Perl. I wrote it as a helper program for my "Turn any Linux computer into SOCKS5 proxy in one command" post.


This is a my, James's and Joshua's node.js knockout entry - an online chess game (half-working). blog engine

I wrote a new engine in Python. I used Werkzeug, SQLAlchemy, Mako, Pygments, Memcached, Sphinx and repoze.profile to make it as awesome as it is.The design followed the "50 ideas for the new website."

Social Scraper

This is an older project from 2007 that I found on my hard drive. It's a social media website scraper (and also some popular news site scraper). It used to scrape data from boingboing,, digg, flickr, furl, reddit, simpy, stumbleupon and wired.

The Little Schemer Book Review

This is a book review of The Little Schemer. The book is a dialogue between you and the authors about interesting examples of Scheme programs and it teaches you to think recursively.

If anyone asks me which book do I recommend for learning basics of Lisp, I recommend this one (and The Seasoned Schemer, see below). It's very fun to read and can be read in one evening.

The Seasoned Schemer Book Review

This is a book review of The Seasoned Schemer. This book continues where The Little Schemer ended and introduces more advanced programming and Scheme concepts such as accumulators, letrec, letcc, call/cc and generators.

Where The Little Schemer can be read in one evening, this book will take one whole day.

The Reasoned Schemer Book Review

This is a book review of The Reasoned Schemer. Though this is not yet a full book review. I currently only had time to go through first few chapters. It's really complicated and takes a lot of effort to understand. One of the authors is Oleg Kiselyov, which instantly makes this book so conceptually difficult that it may take one full week to comprehend some of the topics.

Here is how I summarize this book:

The goal of the book is to show the beauty of relational programming. The authors of the book believe that it is natural to extend functional programming to relational programming. They demonstrate this by extending Scheme with a few new constructs, thereby combining the benefits of both styles. This extension also captures the essence of Prolog, the most well-known logic programming language.

The Little MLer Book Review

This is a book review of The Little MLer. The Little MLer book has two goals. The first and primary goal is to teach you to think recursively about types and programs. The second goal is to expose you to two important topics concerning large programs: dealing with exceptional situations and composing program components.

Having learned the concept of functors in ML, I realized that various programming languages like to call all kinds of unrelated things "functors". So I wrote a post "On Functors".


These are not all the projects that I have pushed to GitHub since last time, but the others are not that interesting. Just for completeness, they are:

  • php2000 - written in 2000, a php routing engine via require().
  • webdev-template - a small webdev template with reset css.
  • node-bufferdiff - compares two node.js buffers fast.
  • node-time - time functions for node.js (had forgotten about Date object).
  • node-jsmin - javascript minification node.js module.
  • node-async - simplest possible asynchronous node.js C++ module (useful as an example).
  • rfb-protocols - implements hextile rfb decoder to RGB buffer in C++.

This is actually more than 20 projects, but not all of them count. :) Anyway, hope you find some of them useful and until the next post!

And just another reminder, I'd love if you followed me on github and twitter! :)