cookies 操作
本教程共 56 篇 · 第 38 篇 · 更新于 2026-08-13 · 约 7 分钟阅读
本节目标:学完能给你的扩展加上读写、删除网站 Cookie 的能力,并理解 cookieStoreId 怎么定位不同的存储区。
38-1 API 概览与权限
cookies API 让扩展直接读写浏览器里的 Cookie。常见用途有:记住登录态、批量清理某站 Cookie、跨标签页同步登录信息、给自动化脚本喂凭证。
它和前面讲过的 storage 不一样。storage 是扩展自己的小仓库,Cookie 是网站存储在浏览器里的数据,两者互不相干。
用 cookies API 前,权限要配两套,少一个都不行。
{
"manifest_version": 3,
"permissions": ["cookies"],
"host_permissions": ["https://www.example.com/"]
}
“cookies” 这个权限是总开关,它允许扩展调用 chrome.cookies 下的方法。但光有它还不够——你要读哪个域的 Cookie,还得在 host_permissions 里声明那个域。
Note读 Cookie 的值,必须对你目标域有 host 权限。只写 “cookies” 而不写域,方法能调用,但拿到的值会是空的或被拦截。
如果你想操作任意网站的 Cookie,host_permissions 直接写 <all_urls> 最省事;只针对个别站点,就写具体域名,符合最小权限原则。
38-2 读取单个 Cookie:get
读一个具体的 Cookie,用 chrome.cookies.get,传 url 和 name 两个关键字段。
chrome.cookies.get({
url: "https://www.example.com/",
name: "sessionid"
}, (cookie) => {
if (cookie) {
console.log("拿到值:", cookie.value);
} else {
console.log("这个 Cookie 不存在");
}
});
url 必须是完整带协议的地址,而且它对应的域要在你的 host_permissions 覆盖范围内,否则读不到。name 就是要找的 Cookie 名。
返回的 cookie 对象里字段不少,常用的有:name(名)、value(值)、domain(所属域)、path(路径)、secure(是否仅 HTTPS)、httpOnly(是否只读)、sameSite(同站策略)、expirationDate(过期时间,秒)、storeId(所在存储区)。
Tipget 找不到时回调拿到的是 null,不是报错。所以判断逻辑里要先判空,别直接访问 cookie.value。
38-3 写入与修改 Cookie:set
写入或覆盖一个 Cookie,都用 chrome.cookies.set。它根据 name + url 命中已有项则覆盖,没有就新建。
chrome.cookies.set({
url: "https://www.example.com/",
name: "token",
value: "abc123",
path: "/",
secure: true,
sameSite: "lax",
expirationDate: Math.floor(Date.now() / 1000) + 3600
}, (cookie) => {
if (cookie) {
console.log("写入成功");
} else {
console.log("写入失败,看 console 报错");
}
});
这里有几个容易踩的坑,我单独拎出来说。
第一,url 是必填,而且 set 时这个 url 的域决定 Cookie 落在哪个站。你想给 example.com 设 Cookie,url 就得是 example.com 下的地址。
第二,secure 为 true 时,url 必须是 https。你拿一个 http 地址去设 secure Cookie,浏览器会直接拒绝。
第三,httpOnly 是能写的。cookies.set 支持 httpOnly 字段(默认 false),你可以通过 API 把一个 Cookie 设成 HttpOnly,不再只是”由网站响应头决定”的属性。
第四,expirationDate 是「自 1970 年至今的秒数」,不是毫秒。很多新手拿 Date.now() 直接塞进去,结果 Cookie 立刻过期。记得除以 1000 并取整。
第五,sameSite 在跨站场景下要配 secure:true,否则浏览器会按更严格的策略处理,Cookie 可能不生效。
Tip想让 Cookie 持久保存,务必设置 expirationDate。不设置的话,多数情况下它会成为会话 Cookie,浏览器一关就没了。
38-4 批量读取:getAll
想一次拿到某域下所有 Cookie,用 chrome.cookies.getAll。它支持按 url、domain、name 等多种条件过滤。
chrome.cookies.getAll({
domain: "example.com"
}, (cookies) => {
console.log("共", cookies.length, "个 Cookie");
cookies.forEach((c) => console.log(c.name, c.value));
});
domain 不带点号时,会匹配主域及其子域;也可以只传 url 来限定某个具体页面。
你还可以通过 storeId 来只取某个存储区的 Cookie,这在多账户、无痕场景下很有用,后面会讲。
NotegetAll 返回的也是数组,可能为空数组(长度 0),这和 get 返回 null 不同,判断时别混了。
38-5 删除 Cookie:remove
删除某个 Cookie,用 chrome.cookies.remove,同样靠 url + name 定位。
chrome.cookies.remove({
url: "https://www.example.com/",
name: "sessionid"
}, (details) => {
if (details) {
console.log("已删除:", details.name);
}
});
删除成功后回调里会带被删项的 name 和 url。删除失败(比如本来就没有)时 details 为 undefined。
说实话,做“一键清理某站登录态”的功能,就是把 getAll 拿到的列表逐个 remove 一遍,逻辑很直白。
38-6 存储区与 cookieStoreId
这是本章的一个重点,也是很多人搞不明白的地方。浏览器里 Cookie 不是存在一个大池子里,而是分「存储区(cookie store)」的。
普通窗口一个存储区,无痕窗口是另一个存储区。Chrome 里默认存储区的 id 是 “0”,无痕窗口有它独立的 id。
你要知道有哪些存储区,用 chrome.cookies.getAllCookieStores:
chrome.cookies.getAllCookieStores((stores) => {
stores.forEach((s) => {
console.log("存储区 id:", s.id, "关联标签页:", s.tabIds);
});
});
tabIds 告诉你这个存储区当前被哪些标签页使用。你想操作无痕窗口里的 Cookie,就得先查到无痕存储区的 id,然后在 get/set/getAll 里带上 cookieStoreId。
chrome.cookies.get({
url: "https://www.example.com/",
name: "sessionid",
storeId: "1"
}, (cookie) => {
console.log(cookie);
});
TipcookieStoreId 不能自己瞎编,必须是 getAllCookieStores 里真实存在的 id。想操作无痕存储区,得先让扩展在无痕模式下跑起来:清单顶层设
"incognito": "spanning"或"split",并且用户在扩展详情页手动开启”允许在无痕模式下运行”。
在 Firefox 里 cookieStoreId 还被用来区分「容器标签」(不同颜色的独立身份),这属于跨浏览器话题,本教程主线是 Chromium,你只要知道在 Chrome 里它主要用来区分普通与无痕存储区即可。
38-7 监听 Cookie 变化:onChanged
如果你想在 Cookie 被网站改动时立刻收到通知,用 chrome.cookies.onChanged 监听。
chrome.cookies.onChanged.addListener((changeInfo) => {
console.log("被改的 Cookie:", changeInfo.cookie.name);
console.log("是删除吗:", changeInfo.removed);
console.log("变化原因:", changeInfo.cause);
});
changeInfo 里有三个关键信息:cookie 是变更后的完整对象、removed 表示是被删还是被改、cause 说明触发原因(比如网页的显式设置、被覆盖等)。
这个功能适合做 Cookie 同步类扩展:用户在某处登录后,站点写了 Cookie,你的监听就能感知并做后续处理。
38-8 常见坑与调试
第一个坑,也是最常犯的:只声明了 “cookies” 权限,没加 host_permissions,结果 get 永远拿 null。要注意,读值要域权限,写值也要域权限。
第二个坑,expirationDate 用了毫秒。Cookie 过期时间是秒,Date.now() 得除以 1000。
第三个坑,secure Cookie 配了 http 的 url。set 时 secure:true 必须搭配 https 地址,否则静默失败。
第四个坑,不会用 httpOnly 字段。cookies.set 支持设置 httpOnly(默认 false),需要 HttpOnly Cookie 时直接传 httpOnly: true 即可。
调试时打开扩展管理页,点开你的后台服务工作者(Service Worker)的「检查」面板,所有 cookies 调用的报错都会出现在那里。也可以在控制台里直接敲 chrome.cookies.getAll 试探,确认权限是否到位。
Tip如果 get 返回 null 但你觉得 Cookie 明明存在,先核对 host_permissions 是否覆盖了该域,再看 url 是否写全了 https 和路径。
38-9 小结
cookies API 的核心就四件事:配权限、读 get、写 set、删 remove,外加按需用 getAll 批量拿、用 onChanged 监听。
权限是这道门的总钥匙:没有 host 权限,方法能调但读不到值。secure、httpOnly、expirationDate 这三个字段的坑,几乎每个新手都会踩一遍,提前了解能省不少时间。
cookieStoreId 用来在多个存储区之间定位,普通窗口和无痕窗口各占一个。要做无痕相关操作,靠的是清单顶层的 incognito 键("spanning" 或 "split")配合用户在扩展管理页手动开启无痕允许,而不是什么”incognito 权限”。
最后提醒一句:Cookie 涉及用户登录态和隐私,能只针对必要域名就不要开 <all_urls>,这既是安全习惯,也能让上架审核更顺。