Skip to content

Instantly share code, notes, and snippets.

@lamchau
Last active March 26, 2024 05:35
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lamchau/718aa36a6e78c2a744ff017709efcf58 to your computer and use it in GitHub Desktop.
Save lamchau/718aa36a6e78c2a744ff017709efcf58 to your computer and use it in GitHub Desktop.
[Chrome/Tampermonkey] Extract *.user.js scripts from LevelDB backup

Restoring Tampermonkey scripts

Chrome stores .user.js scripts in a .ldb, which isn't in a user accessible format to recovery. On some versions of macOS the provided python script can't compile the leveldb package. As a workaround, we can use the node level package to recover our userscripts.

Prerequisite

brew install node
npm install level

Usage

node extract.js "/Users/$(whoami)/Library/Application Support/Google/Chrome Canary/backup/Default/Default/Local Extension Settings/dhdgffkkebhmkfjojejmpbldmpobfkfo"
const fs = require('fs');
const path = require('path');
const level = require('level');
const directory = path.resolve(process.argv.length > 2
? process.argv[2]
: 'dhdgffkkebhmkfjojejmpbldmpobfkfo');
const db = level(directory);
const stream = db.createReadStream();
console.log(`Loading: ${directory}`);
const date = new Date().toISOString();
const outputDirectory = path.resolve(
path.join(
__dirname,
date.slice(0, date.indexOf('T'))
)
);
if (!fs.existsSync(outputDirectory)) {
fs.mkdirSync(outputDirectory, true);
}
console.log(`Saving to: ${outputDirectory}`);
stream.on('data', data => {
const { key, value } = data;
try {
if (value.includes('UserScript')) {
const uuid = key.slice(key.indexOf('#') + 1);
const parsed = JSON.parse(value).value;
const filename = path.join(outputDirectory, `${uuid}.user.js`);
fs.writeFile(filename, parsed, () => {
console.log(`Saved: ${path.basename(filename)}`);
});
}
} catch (err) {
}
});
@AlanI-xx
Copy link

AlanI-xx commented Jul 8, 2021

Worked well, thank you :)

@JustMaier
Copy link

Thank you!

@aljgom
Copy link

aljgom commented Mar 8, 2022

Is there a way to extract the Script Storage variables? I'm thinking it'd be good to have a script that can backup them up in case Chrome deletes everything

@index040722
Copy link

It coundn't find ".../chrome canary/backup/..." on my mac, i can't too. There is no "/chrome canary" folder.
Now I don't know what to do next.

@aljgom
Copy link

aljgom commented Mar 14, 2022

try instead ".../Google/Chrome/Default/Local Extension Settings/..."

It coundn't find ".../chrome canary/backup/..." on my mac, i can't too. There is no "/chrome canary" folder. Now I don't know what to do next.

@Altanis
Copy link

Altanis commented Mar 20, 2022

I use TamperMonkey on Opera GX. What's the path to it?

@index040722
Copy link

try instead ".../Google/Chrome/Default/Local Extension Settings/..."

It coundn't find ".../chrome canary/backup/..." on my mac, i can't too. There is no "/chrome canary" folder. Now I don't know what to do next.

ty

@Brexblime
Copy link

hello anyone can help me with a script please i need help <3

@aljgom
Copy link

aljgom commented Mar 31, 2022

I use TamperMonkey on Opera GX. What's the path to it?

A more general approach seems to be to go to chrome://version/ to find the profile path
then it would be "[profile path]/Local Extension Settings/..."

source: https://superuser.com/a/905304/631364

@gilad-hoshmand-sage
Copy link

gilad-hoshmand-sage commented Apr 4, 2022

Can you add node version required please?

After running npm install level getting - TypeError: level is not a function
Did anyone else get that?

@victoryeo
Copy link

you need to change the line:
const db = level(directory);
to:
const { Level } = require('level')
const db = new Level('example', { valueEncoding: 'json' })

@rakitanc
Copy link

Hi there hope you are doing well

All my userscripts over the years i gathered are gone after the abrupt PC shutdown. Please help me to restore it

Chrome Version 103.0.5060.114 (Official Build) (64-bit)
TM version 4.18.0
Linux OS

If anyone can help me in the situation. It would mean a world to me, I am very devastated right now to what just happened suddenly out of nowhere

you need to change the line: const db = level(directory); to: const { Level } = require('level') const db = new Level('example', { valueEncoding: 'json' })

Screenshot from 2022-10-19 15-41-54

@aljgom
Copy link

aljgom commented Oct 28, 2022

@rakitanc

All my userscripts over the years i gathered are gone after the abrupt PC shutdown. Please help me to restore it

Hey, were you able to figure it out?

@rakitanc
Copy link

@rakitanc

All my userscripts over the years i gathered are gone after the abrupt PC shutdown. Please help me to restore it

Hey, were you able to figure it out?

Not actually

@aljgom
Copy link

aljgom commented Oct 29, 2022

@rakitanc what did you try? Were you able to run this script? Also, did you check if in your Tampermonkey settings you have Enable Userscripts Sync checked? (If you have it checked, you might be able to restore from there too)

@rakitanc
Copy link

@rakitanc what did you try? Were you able to run this script? Also, did you check if in your Tampermonkey settings you have Enable Userscripts Sync checked? (If you have it checked, you might be able to restore from there too)

Thankyou so much brother. It's rare to find people like you nowadays who are helping this way. Because i was already sad and after not getting any help online I lost my hope actually But so happy to hear from you that finally someone came as a ray of hope

Sp just to update you with a good news..I got my scripts back by simply rebooting the PC. I just tried my luck when i didn't know what to do and Fortunately it worked.

But i would like to be in touch with you as i have one more technical issue that you might help with me. So if you don't mind can you share your Telegram, Discord or anything else so i could share it there

Looking forward to hearing from you

Thanks

@wkurten87
Copy link

wkurten87 commented Nov 15, 2022

for those that are looking for this solution in november/22 i have updated this script to work with newer versions, hope this helps somebody!

console.log(`--> LOG - INICIO --------------------`);
const fs = require('fs');
const path = require('path');

const directory = path.resolve(process.argv.length > 2
  ? process.argv[2]
  : 'bhmmomiinigofkjcapegjjndpbikblnp');

const { Level } = require('level')
const db = new Level(directory, { valueEncoding: 'json' });
console.log(`--> LOG - Tentando abrir a base`);
db.open(main);

const { EntryStream } = require('level-read-stream')
const re = new RegExp(`^@source(.*)$`);

function main(e){
	if (e){
		console.log(`--> LOG - ERROR: ${e}`);
	} else {

	console.log(`--> LOG - db status: ${db.status}`);

	console.log(`--> LOG - Loading: ${directory}`);
	const date = new Date().toISOString();
	const outputDirectory = path.resolve(
	  path.join(
		__dirname,
		date.slice(0, date.indexOf('T'))
	  )
	);

	if (!fs.existsSync(outputDirectory)) {
	  fs.mkdirSync(outputDirectory, true);
	}

	var stream = new EntryStream(db);
	stream.on('data', data => {
	  const { key, value } = data;
	  
	  try {
		console.log(`--> LOG - Saving to: ${outputDirectory}`);
		if (re.test(key)){
			console.log(`--> LOG - ACHOU! ->> key: ${key} - value ${value} `);
			
			const uuid = key.slice(key.indexOf('#') + 1);
			console.log(`--> LOG - uuid: ${uuid}`);
			
			//console.log('--> LOG - JSON Stringy' + JSON.stringify(value));
			const parsed = JSON.stringify(value);
			
			const filename = path.join(outputDirectory, `${uuid}.user.js`);
			console.log(`--> LOG - filename: ${filename}`);
			
			fs.writeFile(filename, parsed, () => {
			console.log(`--> LOG - Saved: ${path.basename(filename)}`);
			});
		}
	  } catch (err) {
			console.log(`--> LOG - ERROR: ${err}`);
	  }
	});

	console.log(`--> LOG - FIM --------------------`);
	}
}

@omicr0n
Copy link

omicr0n commented Apr 16, 2023

Updated script above works, thank you. For anyone else that plans to use it you have to run npm install level-read-stream as well before executing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment