Extension Chrome
Nạp các extension (tiện ích mở rộng) dạng unpacked khi khởi chạy bằng extensions. Cả Manifest V2 và V3 đều chạy được, ở cả chế độ có giao diện (headed) lẫn headless, trên Windows và Linux.
Nạp một extension
Truyền một danh sách thư mục extension dạng unpacked — mỗi thư mục chứa một manifest.json — vào launch(), launch_persistent_context() hoặc serve() (.NET: Extensions = new[] { ... }). Extension được nạp vào profile của trình duyệt, nên chỉ có các kiểu khởi chạy incognito là không dùng được (ephemeral_profile=False, launch() của async API, .NET LaunchAsync). Extension dành cho các trình duyệt bạn khởi chạy bằng SDK; trình duyệt được lưu trữ sẵn (hosted) không nạp extension.
from clearcote import launch_persistent_context
ctx = launch_persistent_context(
"./profile",
extensions=["./ext/ublock", "./ext/my-helper"], # unpacked directories
)
page = ctx.pages[0] if ctx.pages else ctx.new_page()
page.goto("https://example.com")import { launchPersistentContext } from "clearcote";
const ctx = await launchPersistentContext("./profile", {
extensions: ["./ext/ublock", "./ext/my-helper"],
});SDK tự đặt cả --load-extension lẫn --disable-extensions-except cho bạn. Việc đi kèm thành cặp này rất quan trọng: nếu đứng một mình, --load-extension sẽ bị bỏ qua khi chạy automation — đó thường là lý do một extension âm thầm không xuất hiện.
Lấy thư mục unpacked
Clearcote nạp thư mục, không nạp file .crx. File .crx là một file ZIP có thêm header chữ ký, nên chỉ cần giải nén là bạn có một thư mục nạp được:
unzip extension.crx -d ./ext/extensionClearcote không thể cài đặt hay cập nhật extension từ Chrome Web Store — các patch quyền riêng tư của upstream đã gỡ bỏ phần tích hợp đó. Hãy đóng gói thư mục unpacked cùng với automation của bạn và tự cập nhật nó: extension nạp theo cách này không bao giờ tự cập nhật. Playwright và Puppeteer cũng dùng đúng mô hình này.
Manifest V2 vẫn hoạt động
Chrome gốc không còn chạy extension Manifest V2 nữa. Clearcote thì vẫn chạy, vì bộ patch quyền riêng tư của upstream đã khôi phục khả năng này — nhờ vậy các content blocker chỉ hỗ trợ MV2 và các công cụ nội bộ cũ vẫn tiếp tục chạy được ở đây, dù đã ngừng hoạt động trên Chrome.
# both of these load and run
ctx = launch_persistent_context("./profile", extensions=["./ext/mv2-tool", "./ext/mv3-tool"])Headless
Extension nạp được ở chế độ headless cũng như headed. Không cần thêm flag, và cũng không cần chạy display server chỉ để extension hoạt động.
ctx = launch_persistent_context("./profile", extensions=["./ext/my-helper"], headless=True)Lưu ý về fingerprint
Extension là code của bạn chạy trong profile của bạn, và Clearcote không che giấu nó. Từ đó dẫn tới hai điều, và cả hai đều nên được quyết định có chủ đích ngay từ đầu thay vì để sau này mới phát hiện ra.
- Extension có thể bị quan sát. Một content script viết lại DOM, inject style hoặc chặn request sẽ làm thay đổi những gì trang đo được. Một site so sánh markup của chính nó với những gì nó đã gửi đi có thể biết được có thứ gì đó đã sửa trang. Điều này đúng với mọi trình duyệt có extension và không phải tín hiệu riêng của Clearcote, nhưng nó vẫn là một tín hiệu.
- Web-accessible resources có thể bị dò. Nếu một extension khai báo
web_accessible_resources, bất kỳ trang nào cũng có thể thử fetchchrome-extension://<id>/<file>và biết được extension đó đang có mặt. Nên ưu tiên các extension không khai báo gì, và cân nhắcuse_dynamic_urlcho những extension buộc phải khai báo.
Nếu mục tiêu của bạn là chặn request chứ không phải cung cấp UI, hãy cân nhắc làm việc đó ở tầng automation bằng CDP Network.setBlockedURLs — nó chặn theo pattern URL, không thêm bề mặt extension nào và vẫn giữ cache của trình duyệt (page.route() của Playwright cũng dùng được nhưng sẽ tắt cache). Xem Cấu hình khuyến nghị để nắm nguyên tắc chung: chỉ spoof những gì cần, và chỉ thêm bề mặt khi nó thực sự xứng đáng.
Xử lý sự cố
- Không có gì xảy ra. Kiểm tra xem đường dẫn có trỏ đúng tới thư mục chứa
manifest.jsonkhông, chứ không phải thư mục cha của nó hay một file.crx. - Content script không bao giờ chạy. Xác nhận rằng pattern
matchesbao phủ URL bạn đang truy cập —http://localhost/*không khớp vớihttp://127.0.0.1:8080/. - Chạy được ở headed nhưng không chạy ở headless. Điều này không nên xảy ra trên bản build này; cả hai đều hoạt động. Nếu bạn gặp trường hợp này, vui lòng mở một issue kèm theo manifest.