Roam JSON export -> Obsidian Markdown, preserving block references

Hi there,

I just converted my Roam DB over to Obsidian. I love being back in control over my notes now :smile:!

Here is the little python script I used to convert Roam’s JSON into Markdown, preserving block references:

Admittedly, it doesn’t have the most fancy command line interface yet, but that’s because it was originally just intended to be used by me.

Might make it more user-friendly, though.

Feedback is welcome!

1 Like

Just used it, it worked like a charm, thanks a lot. Quick question (if you used namespaces in Roam): how did you deal with them? I found that on export they create empty folders but the actual content of the blocks is still contained in the original note where the namespace was created. Thanks!

Hi there, great it worked!

I used namespaces in exactly 1 occasion, which is why I took extra care that they are dealt with. I had noticed that Roam’s Markdown export also created folders, so I decided to mimic that behavior:

[[ [[A]] / [[B]] ]] - creates folder A and puts note B in there if such a note exists

In my case, one note B existed :smile:.

So it can happen that you end up with empty folders - but you can ignore or delete them.

Hi, I am very keen to use this script to import my notes to Obsidian, but I am not sure how to execute this. Is there a simple explainer which you can share? I am stuck at executing the requirements file. Hoping for a reply. Thanks!


So you have Python installed? Are you on Linux, Windows, Mac?

Hey, the conversion just worked out for me, thanks for your response. Also, do I need to run the Markdown importer even after I run your script?

I am still to figure out now the parallels between Roam and Obsidian. For example, in Roam if I have made a page with the name of a person, the page shows all the notes about that person taken over time. When I converted that to Obsidian, the note with the name of the person is blank. References show in Linked mentions, but I would like to see it in the same page similar to Roam. Any idea about that?


Thanks for the script but for some reason it doesn’t seem to work. I keep getting the following error:

    Pass 1: scan all pages
  0%|                                                                                                                                 | 0/1907 [00:00<?, ?it/s]
Traceback (most recent call last):
  File "", line 122, in <module>
    created = page.get('create-time', page['edit-time'])
KeyError: 'edit-time'

Do you know what I could be doing wrong?

I ran into this also. what I found were the timestamps in the roam json file for a particular page had gone bad. they are large integers which represent the number of seconds since january 1, 1970. in my case I found they should be 10-digit integers but were 13 for some reason. so the year was 56,816 instead of, say, 2019. I used perl on the command line to fix them throughout the whole file. I’ll post the one-liner I ran at the shell in a sec.

here is the command I ran (the last word is the name of the Roam json file)

perl -p -i -e 's/:(1[56]\d{8})\d{3},/:$1,/g' roam.json

I’m running into an error as well.
I’ve analyzed my JSON and I don’t have the variable of this py
Thanks beforehand

the uid xFq6qser5 might be a block ref?

I had one very long file that had around 2228 lines (it was from the Day One data I had imported into roam, on one day, the script put out two bullet points for every journal entry). the .md file ended up stopping right around line 2000. not a big deal, since I noticed it and just imported the last few hundred lines by hand, but it was interesting. my next-longest file was only 700-something lines, and that all made it over.