Chrome 扩展数据存放位置:LevelDB 与 IndexedDB

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):

  1. chrome://extensions/ → 点击扩展的”检查视图:Service Worker”或”background page”
  2. 在 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