From 3488008311808c2a29381799b3b4f2cb6dffb5cc Mon Sep 17 00:00:00 2001 From: daijro Date: Thu, 19 Sep 2024 04:52:18 -0500 Subject: [PATCH] pythonlib: Release to PyPi, Update README --- README.md | 25 ++++++++++++++++------- pythonlib/README.md | 35 ++++++++++++++++++++++----------- pythonlib/camoufox/async_api.py | 6 +++++- pythonlib/camoufox/pkgman.py | 2 +- pythonlib/camoufox/py.typed | 1 + pythonlib/camoufox/setup.cfg | 3 +++ pythonlib/camoufox/sync_api.py | 6 +++++- pythonlib/camoufox/utils.py | 9 +++++++-- pythonlib/pyproject.toml | 2 +- 9 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 pythonlib/camoufox/py.typed create mode 100644 pythonlib/camoufox/setup.cfg diff --git a/README.md b/README.md index 318af92..924027e 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ Camoufox aims to be a minimalistic browser for robust fingerprint injection & an - Custom Playwright Juggler implementation for the latest Firefox ✅ - Font spoofing & anti-fingerprinting ✅ - WebRTC IP spoofing ✅ -- Patches from LibreWolf & Ghostery to remove Mozilla services ✅ -- Optimized for memory and speed ✅ +- Debloated & optimized for memory and speed ✅ +- [PyPi package](https://pypi.org/project/camoufox/) for updates & unique fingerprint injection 📦 - Stays up to date with the latest Firefox version 🕓 ## Sponsors @@ -64,8 +64,8 @@ Camoufox is built on top of Firefox/Juggler instead of Chromium because: ### What's planned? - Continue research on potential leaks -- Create a PyPi package for downloading & updating Camoufox -- Integrate [BrowserForge](https://github.com/daijro/browserforge) for fingerprint generation +- ~~Create a PyPi package for downloading & updating Camoufox~~ ✅ +- ~~Integrate [BrowserForge](https://github.com/daijro/browserforge) for fingerprint generation~~ ✅ - Built in TLS fingerprinting protection using [Hazetunnel](https://github.com/daijro/hazetunnel) - Create integration tests - Chromium port (long term) @@ -82,6 +82,12 @@ To spoof fingerprint properties, pass a JSON containing properties to spoof: $ ./launch --config '{"property": "value"}' [...other Firefox arguments] ``` +Or, using the Camoufox Python interface ([see here](https://github.com/daijro/camoufox/tree/main/pythonlib#camoufox-python-interface)): + +```py +>>> with Camoufox(config={"property": "value"}) as browser: +``` + The following attributes can be spoofed:
@@ -355,8 +361,9 @@ Miscellaneous (WebGl spoofing, battery status, etc) #### Debloat/Optimizations - Stripped out/disabled _many, many_ Mozilla services. Runs faster than the original Mozilla Firefox, and uses less memory (200mb) -- Includes the debloat config from PeskyFox & LibreWolf, and others -- Speed optimizations from FastFox, and other network optimizations +- Patches from LibreWolf & Ghostery to help remove telemetry & bloat +- Debloat config from PeskyFox, LibreWolf, and others +- Speed & network optimizations from FastFox - Removed all CSS animations - Minimalistic theming - etc. @@ -369,6 +376,7 @@ Miscellaneous (WebGl spoofing, battery status, etc) - Addons are not allowed to open tabs - Addons are automatically enabled in Private Browsing mode - Addons are automatically pinned to the toolbar +- Fixes DNS leaks with uBO prefetching ## Stealth Performance @@ -409,6 +417,9 @@ Camoufox does **not** fully support injecting Chromium fingerprints. Some WAFs ( ## Playwright Usage +> [!NOTE] +> It is recommended to use Camoufox's Python interface instead. See [here](https://github.com/daijro/camoufox/tree/main/pythonlib#camoufox-python-interface) for more information. + Camoufox is fully compatible with your existing Playwright code. You only have to change your browser initialization: ```py @@ -500,7 +511,7 @@ graph TD end ``` -This was originally forked from the LibreWolf build system. +This was originally based on the LibreWolf build system. ## Build CLI diff --git a/pythonlib/README.md b/pythonlib/README.md index a12d9d6..d91af1d 100644 --- a/pythonlib/README.md +++ b/pythonlib/README.md @@ -1,6 +1,6 @@ # Camoufox Python Interface -#### This is the Python library for Camoufox. +#### Lightweight wrapper around the Playwright API to help launch Camoufox. > [!WARNING] > This is still experimental and in active development! @@ -10,17 +10,23 @@ First, install the `camoufox` package: ```bash -git clone --depth 1 https://github.com/camoufox -cd camoufox/pythonlib -pip install . +pip install -U camoufox ``` Then, download the Camoufox browser: +**Windows** + ```bash camoufox fetch ``` +**MacOS & Linux** + +```bash +python3 -m camoufox fetch +``` + To uninstall, run `camoufox remove`.
@@ -34,9 +40,9 @@ Camoufox is fully compatible with your existing Playwright code. You only have t ```python from camoufox.sync_api import Camoufox -with Camoufox() as browser: +with Camoufox(headless=False) as browser: page = browser.new_page() - page.goto("https://www.browserscan.net/") + page.goto("https://example.com/") ``` #### Async API @@ -44,15 +50,17 @@ with Camoufox() as browser: ```python from camoufox.async_api import AsyncCamoufox -async with AsyncCamoufox() as browser: +async with AsyncCamoufox(headless=False) as browser: page = await browser.new_page() - await page.goto("https://www.browserscan.net/") + await page.goto("https://example.com") ``` +
Parameters ``` Launches a new browser instance for Camoufox. +Accepts all Playwright Firefox launch options, along with the following: Parameters: playwright (Playwright): @@ -80,6 +88,7 @@ Parameters: **launch_options (Dict[str, Any]): Additional Firefox launch options. ``` +
--- @@ -98,7 +107,7 @@ with Camoufox( } ) as browser: page = browser.new_page() - page.goto("https://www.browserscan.net/") + page.goto("https://www.browserscan.net/webrtc") ```
@@ -118,7 +127,11 @@ fg = FingerprintGenerator(browser='firefox') # Launch Camoufox with a random Firefox fingerprint with Camoufox(fingerprint=fg.generate()) as browser: page = browser.new_page() - page.goto("https://www.browserscan.net/") + page.goto("https://example.com/") ``` ---- \ No newline at end of file +
+ +**Note:** As of now, some properties from BrowserForge fingerprints will not be passed to Camoufox. This is due to the outdated fingerprint dataset from Apify's fingerprint-suite (see [here](https://github.com/apify/fingerprint-suite/discussions/308)). Properties will be re-enabled as soon as an updated dataset is available. + +--- diff --git a/pythonlib/camoufox/async_api.py b/pythonlib/camoufox/async_api.py index 338f1da..ab98eb1 100644 --- a/pythonlib/camoufox/async_api.py +++ b/pythonlib/camoufox/async_api.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Union from browserforge.fingerprints import Fingerprint, Screen from playwright.async_api import Browser, Playwright, PlaywrightContextManager @@ -42,6 +42,7 @@ async def AsyncNewBrowser( fonts: Optional[List[str]] = None, args: Optional[List[str]] = None, executable_path: Optional[str] = None, + env: Optional[Dict[str, Union[str, float, bool]]] = None, **launch_options: Dict[str, Any] ) -> Browser: """ @@ -70,6 +71,8 @@ async def AsyncNewBrowser( The arguments to pass to the browser. executable_path (Optional[str]): The path to the Camoufox browser executable. + env (Optional[Dict[str, Union[str, float, bool]]]): + The environment variables to set. **launch_options (Dict[str, Any]): Additional Firefox launch options. """ @@ -84,5 +87,6 @@ async def AsyncNewBrowser( fonts=fonts, args=args, executable_path=executable_path, + env=env, ) return await playwright.firefox.launch(**opt, **launch_options) diff --git a/pythonlib/camoufox/pkgman.py b/pythonlib/camoufox/pkgman.py index c709348..d4f70bb 100644 --- a/pythonlib/camoufox/pkgman.py +++ b/pythonlib/camoufox/pkgman.py @@ -279,7 +279,7 @@ def get_path(file: str) -> str: Get the path to the camoufox executable. """ if OS_NAME == 'mac': - return str(camoufox_path() / 'Camoufox.app' / 'Contents' / 'Resources' / file) + return os.path.abspath(camoufox_path() / 'Camoufox.app' / 'Contents' / 'Resources' / file) return str(camoufox_path() / file) diff --git a/pythonlib/camoufox/py.typed b/pythonlib/camoufox/py.typed new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/pythonlib/camoufox/py.typed @@ -0,0 +1 @@ + diff --git a/pythonlib/camoufox/setup.cfg b/pythonlib/camoufox/setup.cfg new file mode 100644 index 0000000..b1e5beb --- /dev/null +++ b/pythonlib/camoufox/setup.cfg @@ -0,0 +1,3 @@ +[vermin] +verbose = 1 +processes = 4 diff --git a/pythonlib/camoufox/sync_api.py b/pythonlib/camoufox/sync_api.py index 3130f45..1aa4980 100644 --- a/pythonlib/camoufox/sync_api.py +++ b/pythonlib/camoufox/sync_api.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Union from browserforge.fingerprints import Fingerprint, Screen from playwright.sync_api import Browser, Playwright, PlaywrightContextManager @@ -42,6 +42,7 @@ def NewBrowser( fonts: Optional[List[str]] = None, args: Optional[List[str]] = None, executable_path: Optional[str] = None, + env: Optional[Dict[str, Union[str, float, bool]]] = None, **launch_options: Dict[str, Any] ) -> Browser: """ @@ -70,6 +71,8 @@ def NewBrowser( The arguments to pass to the browser. executable_path (Optional[str]): The path to the Camoufox browser executable. + env (Optional[Dict[str, Union[str, float, bool]]]): + The environment variables to set. **launch_options (Dict[str, Any]): Additional Firefox launch options. """ @@ -84,5 +87,6 @@ def NewBrowser( fonts=fonts, args=args, executable_path=executable_path, + env=env, ) return playwright.firefox.launch(**opt, **launch_options) diff --git a/pythonlib/camoufox/utils.py b/pythonlib/camoufox/utils.py index 864adeb..c6c7cf8 100644 --- a/pythonlib/camoufox/utils.py +++ b/pythonlib/camoufox/utils.py @@ -2,11 +2,12 @@ import os import sys from os import environ from random import randrange -from typing import Any, Dict, List, Optional, Tuple, TypeAlias, Union +from typing import Any, Dict, List, Optional, Tuple, Union, cast import numpy as np import orjson from browserforge.fingerprints import Fingerprint, Screen +from typing_extensions import TypeAlias from ua_parser import user_agent_parser from .addons import ( @@ -162,6 +163,7 @@ def get_launch_options( fonts: Optional[List[str]] = None, args: Optional[List[str]] = None, executable_path: Optional[str] = None, + env: Optional[Dict[str, Union[str, float, bool]]] = None, ) -> Dict[str, Any]: """ Builds the launch options for the Camoufox browser. @@ -212,7 +214,10 @@ def get_launch_options( # Launch threaded_try_load_addons(get_debug_port(args), addons) - env_vars = {**get_env_vars(config, target_os), **environ} + env_vars = { + **get_env_vars(config, target_os), + **(cast(Dict[str, Union[str, float, bool]], environ) if env is None else env), + } return { "executable_path": executable_path or get_path(LAUNCH_FILE[OS_NAME]), "args": args, diff --git a/pythonlib/pyproject.toml b/pythonlib/pyproject.toml index 18d70d4..2acca10 100644 --- a/pythonlib/pyproject.toml +++ b/pythonlib/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "camoufox" -version = "1.0.0" +version = "0.1.0b3" description = "Wrapper around Playwright to help launch Camoufox" authors = ["daijro "] license = "MIT"