I’ve been using Zen Browser for over 6 months now. And I think it’s time I switch back to Brave. The initial motivation to use Zen Browser was because https://lobste.rs/ boycotted Brave and blocked access from Brave. Now that the block seems to have been removed, I’m eager to get back to Brave. Vertical tabs feature is also supported in Brave as well as tab group, like space in Zen Browser, so I don’t think there’s really a reason for me to continue using Zen Browser.

Some dislikes and pain points I encountered using Zen Browser:

  • Hassle to set up a bunch of ad blockers that are built-in in Brave.
  • Chrome extensions are more widely available compared to Firefox counterpart.
  • Occasional UI breaking changes.

I wasn’t able to find a feature to export bookmarks from Zen Browser so querying the local SQLite database was the only option. I’ll share a few useful SQL snippets.

Connecting to places.sqlite

Firefox, or Zen Browser, keeps its bookmarks in places.sqlite. On macOS, the path to this file is:

ls ~/Library/Application\ Support/Zen/Profiles/*/places.sqlite

You can either use sqlite3 or a SQL client like DBeaver to connect to the database using the path.

Getting all bookmarks with folder names, titles and URLs

Run this query to select all bookmarks:

SELECT
  b.id,
  parent.title AS folder_name,
  b.title AS bookmark_title,
  p.url
FROM moz_bookmarks b
JOIN moz_places p ON b.fk = p.id
LEFT JOIN moz_bookmarks parent ON b.parent = parent.id
WHERE b.type = 1
ORDER BY folder_name, bookmark_title

Result:

| id | folder_name | bookmark_title | url                        |
|----+-------------+----------------+----------------------------|
| 18 | Blogs       | Lobsters       | https://lobste.rs/         |
| 20 | Blogs       | Alex MacCaw    | https://alexmaccaw.com/    |
| 26 | Blogs       | Paul Graham    | http://www.paulgraham.com/ |
  • NOTE:
    • moz_bookmarks.type = 1 are bookmarks
    • moz_bookmarks.type = 2 are folders

Finding any duplicates (by URL)

There could be some duplicates that might be worth looking into:

SELECT
  p.url,
  COUNT(*) AS count
FROM moz_bookmarks b
JOIN moz_places p ON b.fk = p.id
WHERE b.type = 1
GROUP BY p.url
HAVING COUNT(*) > 1
ORDER BY count DESC;

Exporting as importable HTML

Save this query as a file export-bookmarks.sql:

WITH RECURSIVE walk AS (
  SELECT
    b.id,
    b.title,
    b.parent,
    b.type,
    p.url,
    b.position,
    1 AS level,
    printf('%06d', b.position) AS path,
    'enter' AS phase
  FROM moz_bookmarks b
  LEFT JOIN moz_places p ON b.fk = p.id
  WHERE b.parent IN (2, 3, 4)

  UNION ALL

  SELECT
    b.id,
    b.title,
    b.parent,
    b.type,
    p.url,
    b.position,
    w.level + 1,
    w.path || '.' || printf('%06d', b.position),
    'enter'
  FROM moz_bookmarks b
  LEFT JOIN moz_places p ON b.fk = p.id
  JOIN walk w ON b.parent = w.id
  WHERE w.phase = 'enter'

  UNION ALL

  SELECT
    id,
    title,
    parent,
    type,
    url,
    position,
    level,
    path || '.zzzzzz',
    'exit'
  FROM walk
  WHERE phase = 'enter' AND type = 2
)
SELECT
  CASE
    WHEN phase = 'enter' AND type = 2 THEN
      printf(
        '%s<DT><H3>%s</H3>%s%s<DL><p>',
        printf('%*s', level * 2, ''),
        COALESCE(title, ''),
        char(10),
        printf('%*s', level * 2, '')
      )

    WHEN phase = 'enter' AND type = 1 THEN
      printf(
        '%s<DT><A HREF="%s">%s</A>',
        printf('%*s', level * 2, ''),
        url,
        COALESCE(title, '')
      )

    WHEN phase = 'exit' THEN
      printf(
        '%s</DL><p>',
        printf('%*s', (level - 1) * 2, '')
      )
  END AS html
FROM walk
WHERE type IN (1, 2)
ORDER BY path;

Run the query and generate an HTML file for import:

sqlite3 -batch -noheader \
  "$HOME/Library/Application Support/Zen/Profiles/f16znh1m.Default (release)/places.sqlite" \
  < export-bookmarks.sql \
| sed '1i\
<!DOCTYPE NETSCAPE-Bookmark-file-1>\
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">\
<TITLE>Bookmarks</TITLE>\
<H1>Bookmarks</H1>\
<DL><p>' \
> ~/Desktop/bookmarks.html

echo "</DL><p>" >> ~/Desktop/bookmarks.html