Chrome 扩展的 chrome.storage.local 数据并不存在普通的 localStorage 里,而是存在用户数据目录下以 LevelDB 格式保存的独立数据库中。
数据存放路径
Windows
# Chrome
C:\Users\用户名\AppData\Local\Google\Chrome\User Data\Default\Local Extension Settings\
# Edge
C:\Users\用户名\AppData\Local\Microsoft\Edge\User Data\Default\Local Extension Settings\
每个扩展一个子目录,目录名是扩展 ID:
Local Extension Settings\
├── nkbihfbeogaeaoehlefnkodbefgpgknn\ ← MetaMask
│ ├── LOG
│ ├── CURRENT
│ ├── MANIFEST-000001
│ └── 000003.ldb
└── cjpalhdlnbpafiamejdnhcphjbkeiagm\ ← uBlock Origin
里面是 LevelDB 格式,不能直接用文本编辑器读取。
macOS
~/Library/Application Support/Google/Chrome/Default/Local Extension Settings/
找到扩展 ID
打开 chrome://extensions/,开启右上角开发者模式,即可看到每个扩展的 ID(32 位小写字母)。
在 DevTools 中读取扩展数据
打开扩展的背景页(Service Worker):
chrome://extensions/→ 点击扩展的”检查视图:Service Worker”或”background page”- 在 DevTools Console 中:
// 读取所有 storage.local 数据
chrome.storage.local.get(null, console.log);
// 或
const data = await chrome.storage.local.get();
console.log(data);
其他存储类型路径
Default\
├── Local Extension Settings\ ← chrome.storage.local(LevelDB)
├── Extension State\ ← chrome.storage.session
├── IndexedDB\ ← IndexedDB
│ └── chrome-extension_xxx.indexeddb.leveldb
└── Session Storage\ ← sessionStorage
AdsPower 多配置文件批量同步扩展数据
AdsPower 的每个浏览器配置文件存在各自的 cache 目录下,批量同步扩展 LevelDB 数据:
import json
import shutil
import sys
from pathlib import Path
from datetime import datetime
from tqdm import tqdm
CONFIG_FILE = Path("config.json")
EXT_DIR = "mcohilncbfahbmgdjkbpemcciiolgcge" # 扩展 ID
DEFAULT_CONFIG = {
"src": r"D:\.ADSPOWER_GLOBAL\cache",
"dst": r"D:\ads\.ADSPOWER_GLOBAL\cache"
}
if not CONFIG_FILE.exists():
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(DEFAULT_CONFIG, f, indent=4, ensure_ascii=False)
print("已创建 config.json,请修改后重新运行")
sys.exit(0)
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
config = json.load(f)
src_root = Path(config["src"])
dst_root = Path(config["dst"])
# 找出所有包含目标扩展数据的配置文件目录
tasks = [
d for d in src_root.iterdir()
if d.is_dir() and (d / "Default" / "Local Extension Settings" / EXT_DIR).exists()
]
print(f"发现 {len(tasks)} 个配置需要同步")
for index, cache_dir in enumerate(tasks, 1):
src = cache_dir / "Default" / "Local Extension Settings" / EXT_DIR
dst = dst_root / cache_dir.name / "Default" / "Local Extension Settings" / EXT_DIR
print(f"\n[{index}/{len(tasks)}] {cache_dir.name}")
# 备份旧目录(加时间戳,不直接删除)
if dst.exists():
backup = dst.parent / f"{dst.name}_backup_{datetime.now():%Y%m%d_%H%M%S}"
dst.rename(backup)
# 只保留最近 5 个备份
backups = sorted(dst.parent.glob(f"{dst.name}_backup_*"), key=lambda p: p.stat().st_mtime, reverse=True)
for old in backups[5:]:
shutil.rmtree(old)
dst.mkdir(parents=True, exist_ok=True)
files = [f for f in src.rglob("*") if f.is_file()]
with tqdm(total=len(files), desc=cache_dir.name, unit="file", ncols=100) as pbar:
for file in files:
target = dst / file.relative_to(src)
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(file, target)
pbar.update(1)
print("\n全部同步完成")
关键点:
shutil.rmtree太暴力,改用rename加时间戳备份- 保留最近 5 个备份,自动清理旧版本
tqdm显示每个目录的文件级复制进度
打包成独立 exe:
pip install pyinstaller tqdm
pyinstaller -F sync_ext.py