Source

Converting Sourcemaps to Original JavaScript/TypeScript Sourcecode

Introduction

Hi everyone! This is going to be a short and quick tutorial on how to download sourcemap files and convert them into the original JavaScript source code. Here’s an example of minified code from a Next.js website:

Minified code

And here is the same code after the browser has done its magic and reconstructed the original code using sourcemaps:

Original code

Take a look at the bottom toolbar — it shows whether the displayed code is a bundled file or the original source file.

Our goal is to download this original file to our local system. Currently, you can view the original code in browsers for websites that publicly publish their sourcemaps, but browsers don’t let you download the original code in bulk. This means you can individually download each file from the developer tools, but you can’t download an entire directory at once. This is a problem because websites usually contain hundreds (if not thousands) of source files.

I’m not aware of any way to do this using browser extensions. There is one prominent Chrome extension that mostly works: ResourcesSaverExt, but it’s currently experiencing issues with Webpack. My understanding is that this is a Google Chrome limitation, as described in this issue.

Instead, we’ll use Mitmproxy to intercept all web requests and log the sourcemap URLs, and then use Sourcemapper to download and reconstruct the original code using those sourcemaps.


Step 1: Install and Run Mitmproxy

Mitmproxy is a free and open-source proxy that you can use to route all your network requests through. It’s extremely powerful and provides a very flexible scripting environment. You can follow the instructions on the official website to install it.

Once installation is complete, run the proxy from your terminal and set your system proxy to route all requests through it. After that, open any website in your browser. You should see all the requests being logged in the terminal:

Mitmproxy working

Perfect! Now clear the list of flows by pressing z.


Step 2: Open the Target Website

Next, open the target website in your browser. This won’t automatically trigger the loading of sourcemap files. You need to open the developer tools and go to the Sources tab in Chrome or the Debugger tab in Firefox. Once you do that, you’ll see a bunch of new requests in Mitmproxy ending with .js.map:

Mitmproxy sourcemaps

At this point, press w in Mitmproxy and enter a name for the dump file where these intercepted flows will be stored. I’ll assume you named it dump.


Step 3: Extract Sourcemap URLs

Create a script.py file containing a bit of code to filter the dump file you just created. In my case, this is what it looked like:

def request(flow):
    if "targetdomain" in flow.request.url and flow.request.url.endswith(".map"):
        print(flow.request.url)

Replace "targetdomain" with the domain you’re targeting. This filters out any intercepted requests from other domains you’re not interested in. We’re also filtering for .map since sourcemap files always end with that extension.

Now, run this command to process the dump file using your script:

mitmdump -q -s script.py -r dump

This will print each sourcemap URL on a new line in the terminal, like this:

https://example.com/a.js.map  
https://example.com/b.js.map

Step 4: Pipe Sourcemap URLs to Sourcemapper

This is the final step. You’ll now pipe these URLs into Sourcemapper. This tool downloads each sourcemap and reconstructs the original source code. A typical Sourcemapper command looks like this:

sourcemapper -output outputdirectory -url https://sampleurl.com

Instead of running this manually for each URL, you can use:

mitmdump -q -s script.py -r dump | xargs -n 1 sourcemapper -output output -url

Once the command finishes, the original source code will be saved in the output directory.


Issues with Sourcemapper

I did run into a few issues with Sourcemapper. For instance, the file structure it produces doesn’t exactly match what you see in the browser. All the files are recreated, but the nesting might be off. This was acceptable in my case, but you may want to investigate further depending on your use case.


Conclusion

I’m glad I can view the original JS/TS code of most websites. However, if you want to keep your code private, make sure you’re not publicly publishing your sourcemaps. Almost all major build tools support removing sourcemaps from public directories.

P.S.: At one point, I considered patching Firefox’s source code to dump all the generated sourcemaps to the local file system. That’s probably the best way to get the most accurate source code. However, Firefox’s build process is slow, and the method I’ve shared here worked well enough for my needs.

Newsletter

×

If you liked what you read then I am sure you will enjoy a newsletter of the content I create. I send it out every other month. It contains new stuff that I make, links I find interesting on the web, and occasional discount coupons for my book. Join the 5000+ other people who receive my newsletter:

I send out the newsletter once every other month. No spam, I promise + you can unsubscribe at anytime

✍️ Comments

Be the first to leave a comment! 🎉

Say something

Send me an email when someone comments on this post.

Thank you!

Your comment has been submitted and will be published once it has been approved. 😊

OK