mirror of
https://github.com/FlareSolverr/FlareSolverr.git
synced 2026-09-24 11:10:12 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe5e1e8cea | ||
|
|
93125d6ea6 | ||
|
|
cdb8748734 | ||
|
|
c6eb8f5323 | ||
|
|
cecf130c65 | ||
|
|
3ae649ae20 | ||
|
|
833bfca77b | ||
|
|
e0fac5030d | ||
|
|
e263039eaa | ||
|
|
b5f92e5e57 | ||
|
|
24e7893da5 | ||
|
|
a4370cc0a0 | ||
|
|
c4621e40a7 | ||
|
|
63f48e17ee | ||
|
|
bc4d136fa7 | ||
|
|
716451bc30 | ||
|
|
0f05ed8fc9 | ||
|
|
237faf1730 | ||
|
|
b21642624b | ||
|
|
79154abcf4 |
@@ -48,8 +48,6 @@ body:
|
||||
- FlareSolverr User-Agent (see log traces or / endpoint):
|
||||
- Are you using a VPN: [yes/no]
|
||||
- Are you using a Proxy: [yes/no]
|
||||
- Are you using Captcha Solver: [yes/no]
|
||||
- If using captcha solver, which one:
|
||||
- URL to test this issue:
|
||||
render: markdown
|
||||
validations:
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Auto tag
|
||||
uses: Klemensas/action-autotag@stable
|
||||
|
||||
@@ -18,14 +18,14 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Downcase repo
|
||||
run: echo REPOSITORY=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
|
||||
- name: Docker meta
|
||||
id: docker_meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: |
|
||||
${{ env.REPOSITORY }},enable=${{ github.event_name != 'pull_request' }}
|
||||
@@ -37,27 +37,27 @@ jobs:
|
||||
latest=auto
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GH_PAT }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
body: ${{ steps.github_changelog.outputs.changelog }}
|
||||
env:
|
||||
@@ -39,24 +39,24 @@ jobs:
|
||||
os: [ubuntu-22.04, windows-latest]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@v7
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Build artifacts
|
||||
run: |
|
||||
python -m pip install -r requirements.txt
|
||||
python -m pip install pyinstaller==6.20.0
|
||||
python -m pip install pyinstaller==6.22.2
|
||||
cd src
|
||||
python build_package.py
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: ./dist/flaresolverr_*
|
||||
env:
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## v3.5.2 (2026/09/12)
|
||||
* Update build_package.py
|
||||
* Disable breaking Local Network Access Checks popup
|
||||
* Make the challenge wait timeout configurable. Thanks @aki-ks
|
||||
* Fixed multiple buttons bug for tabs_till_verify. Thanks @denis-svg
|
||||
* Fix cookies being retrieved before waitInSeconds delay. Thanks @Br1an67
|
||||
* Bump dependencies & Chromium
|
||||
|
||||
## v3.5.0 (2026/05/26)
|
||||
* Add formatting to log file
|
||||
* Resolve turnstile captcha. Thanks @denis-svg
|
||||
|
||||
+5
-5
@@ -67,17 +67,17 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
CMD ["/usr/local/bin/python", "-u", "/app/flaresolverr.py"]
|
||||
|
||||
# Local build
|
||||
# docker build -t ngosang/flaresolverr:3.5.0 .
|
||||
# docker run -p 8191:8191 ngosang/flaresolverr:3.5.0
|
||||
# docker build -t ngosang/flaresolverr:3.5.2 .
|
||||
# docker run -p 8191:8191 ngosang/flaresolverr:3.5.2
|
||||
|
||||
# Multi-arch build
|
||||
# docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
# docker buildx create --use
|
||||
# docker buildx build -t ngosang/flaresolverr:3.5.0 --platform linux/386,linux/amd64,linux/arm/v7,linux/arm64/v8 .
|
||||
# docker buildx build -t ngosang/flaresolverr:3.5.2 --platform linux/386,linux/amd64,linux/arm/v7,linux/arm64/v8 .
|
||||
# add --push to publish in DockerHub
|
||||
|
||||
# Test multi-arch build
|
||||
# docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
# docker buildx create --use
|
||||
# docker buildx build -t ngosang/flaresolverr:3.5.0 --platform linux/arm/v7 --load .
|
||||
# docker run -p 8191:8191 --platform linux/arm/v7 ngosang/flaresolverr:3.5.0
|
||||
# docker buildx build -t ngosang/flaresolverr:3.5.2 --platform linux/arm/v7 --load .
|
||||
# docker run -p 8191:8191 --platform linux/arm/v7 ngosang/flaresolverr:3.5.2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Diego Heras (ngosang / ngosang@hotmail.es)
|
||||
Copyright (c) 2026 Diego Heras (ngosang / ngosang@hotmail.es)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -35,7 +35,7 @@ already included within the image.
|
||||
|
||||
Docker images are available in:
|
||||
|
||||
- GitHub Registry => https://github.com/orgs/FlareSolverr/packages/container/package/flaresolverr
|
||||
- GitHub Registry => https://github.com/FlareSolverr/FlareSolverr/pkgs/container/flaresolverr
|
||||
- DockerHub => https://hub.docker.com/r/flaresolverr/flaresolverr
|
||||
|
||||
Supported architectures are:
|
||||
@@ -58,7 +58,7 @@ If you prefer the `docker cli` execute the following command:
|
||||
```bash
|
||||
docker run -d \
|
||||
--name=flaresolverr \
|
||||
-p 8191:8191 \
|
||||
-p 127.0.0.1:8191:8191 \
|
||||
-e LOG_LEVEL=info \
|
||||
--restart unless-stopped \
|
||||
ghcr.io/flaresolverr/flaresolverr:latest
|
||||
@@ -67,13 +67,15 @@ docker run -d \
|
||||
**Command Prompt or Powershell**
|
||||
|
||||
```cmd
|
||||
docker run -d --name=flaresolverr -p 8191:8191 -e LOG_LEVEL=info --restart unless-stopped ghcr.io/flaresolverr/flaresolverr:latest
|
||||
docker run -d --name=flaresolverr -p 127.0.0.1:8191:8191 -e LOG_LEVEL=info --restart unless-stopped ghcr.io/flaresolverr/flaresolverr:latest
|
||||
```
|
||||
|
||||
If your host OS is Debian, make sure `libseccomp2` version is 2.5.x. You can check the version with `sudo apt-cache policy libseccomp2`
|
||||
and update the package with `sudo apt install libseccomp2=2.5.1-1~bpo10+1` or `sudo apt install libseccomp2=2.5.1-1+deb11u1`.
|
||||
Remember to restart the Docker daemon and the container after the update.
|
||||
|
||||
DO NOT expose FlareSolverr to the internet, as it can be abused.
|
||||
|
||||
### Precompiled binaries
|
||||
|
||||
> **Warning**
|
||||
@@ -277,24 +279,25 @@ This works like `request.get`, with the addition of the postData parameter. Note
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Name | Default | Notes |
|
||||
| ------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| LOG_LEVEL | info | Verbosity of the logging. Use `LOG_LEVEL=debug` for more information. |
|
||||
| LOG_FILE | none | Path to capture log to file. Example: `/config/flaresolverr.log`. |
|
||||
| LOG_HTML | false | Only for debugging. If `true` all HTML that passes through the proxy will be logged to the console in `debug` level. |
|
||||
| PROXY_URL | none | URL for proxy. Will be overwritten by `request` or `sessions` proxy, if used. Example: `http://127.0.0.1:8080`. |
|
||||
| PROXY_USERNAME | none | Username for proxy. Will be overwritten by `request` or `sessions` proxy, if used. Example: `testuser`. |
|
||||
| PROXY_PASSWORD | none | Password for proxy. Will be overwritten by `request` or `sessions` proxy, if used. Example: `testpass`. |
|
||||
| CAPTCHA_SOLVER | none | Captcha solving method. It is used when a captcha is encountered. See the Captcha Solvers section. |
|
||||
| TZ | UTC | Timezone used in the logs and the web browser. Example: `TZ=Europe/London`. |
|
||||
| LANG | none | Language used in the web browser. Example: `LANG=en_GB`. |
|
||||
| HEADLESS | true | Only for debugging. To run the web browser in headless mode or visible. |
|
||||
| DISABLE_MEDIA | false | To disable loading images, CSS, and other media in the web browser to save network bandwidth. |
|
||||
| TEST_URL | https://www.google.com | FlareSolverr makes a request on start to make sure the web browser is working. You can change that URL if it is blocked in your country. |
|
||||
| PORT | 8191 | Listening port. You don't need to change this if you are running on Docker. |
|
||||
| HOST | 0.0.0.0 | Listening interface. You don't need to change this if you are running on Docker. |
|
||||
| PROMETHEUS_ENABLED | false | Enable Prometheus exporter. See the Prometheus section below. |
|
||||
| PROMETHEUS_PORT | 8192 | Listening port for Prometheus exporter. See the Prometheus section below. |
|
||||
| Name | Default | Notes |
|
||||
|----------------------| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| LOG_LEVEL | info | Verbosity of the logging. Use `LOG_LEVEL=debug` for more information. |
|
||||
| LOG_FILE | none | Path to capture log to file. Example: `/config/flaresolverr.log`. |
|
||||
| LOG_HTML | false | Only for debugging. If `true` all HTML that passes through the proxy will be logged to the console in `debug` level. |
|
||||
| PROXY_URL | none | URL for proxy. Will be overwritten by `request` or `sessions` proxy, if used. Example: `http://127.0.0.1:8080`. |
|
||||
| PROXY_USERNAME | none | Username for proxy. Will be overwritten by `request` or `sessions` proxy, if used. Example: `testuser`. |
|
||||
| PROXY_PASSWORD | none | Password for proxy. Will be overwritten by `request` or `sessions` proxy, if used. Example: `testpass`. |
|
||||
| CAPTCHA_SOLVER | none | Captcha solving method. It is used when a captcha is encountered. See the Captcha Solvers section. |
|
||||
| TZ | UTC | Timezone used in the logs and the web browser. Example: `TZ=Europe/London`. |
|
||||
| LANG | none | Language used in the web browser. Example: `LANG=en_GB`. |
|
||||
| HEADLESS | true | Only for debugging. To run the web browser in headless mode or visible. |
|
||||
| DISABLE_MEDIA | false | To disable loading images, CSS, and other media in the web browser to save network bandwidth. |
|
||||
| BROWSER_WAIT_TIMEOUT | 1 | Seconds to wait for the web browser to reach an expected page state on each attempt. Increase it on slow hosts or slow websites. |
|
||||
| TEST_URL | https://www.google.com | FlareSolverr makes a request on start to make sure the web browser is working. You can change that URL if it is blocked in your country. |
|
||||
| PORT | 8191 | Listening port. You don't need to change this if you are running on Docker. |
|
||||
| HOST | 0.0.0.0 | Listening interface. You don't need to change this if you are running on Docker. |
|
||||
| PROMETHEUS_ENABLED | false | Enable Prometheus exporter. See the Prometheus section below. |
|
||||
| PROMETHEUS_PORT | 8192 | Listening port for Prometheus exporter. See the Prometheus section below. |
|
||||
|
||||
Environment variables are set differently depending on the operating system. Some examples:
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "flaresolverr",
|
||||
"version": "3.5.0",
|
||||
"version": "3.5.2",
|
||||
"description": "Proxy server to bypass Cloudflare protection",
|
||||
"author": "Diego Heras (ngosang / ngosang@hotmail.es)",
|
||||
"license": "MIT"
|
||||
|
||||
+7
-7
@@ -1,14 +1,14 @@
|
||||
bottle==0.13.4
|
||||
waitress==3.0.2
|
||||
selenium==4.39.0
|
||||
selenium==4.47.0
|
||||
func-timeout==4.3.5
|
||||
prometheus-client==0.23.1
|
||||
prometheus-client==0.26.0
|
||||
# Required by undetected_chromedriver
|
||||
requests==2.32.5
|
||||
certifi==2025.11.12
|
||||
websockets==15.0.1
|
||||
packaging==25.0
|
||||
requests==2.34.2
|
||||
certifi==2026.7.22
|
||||
websockets==17.0.1
|
||||
packaging==26.3
|
||||
# Only required for Linux and macOS
|
||||
xvfbwrapper==0.2.16; platform_system != "Windows"
|
||||
xvfbwrapper==0.2.29; platform_system != "Windows"
|
||||
# Only required for Windows
|
||||
pefile==2024.8.26; platform_system == "Windows"
|
||||
|
||||
@@ -26,7 +26,7 @@ def clean_files():
|
||||
|
||||
def download_chromium():
|
||||
# https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Linux_x64/
|
||||
revision = "1522586" if os.name == 'nt' else '1522586'
|
||||
revision = "1681099" if os.name == 'nt' else '1681097'
|
||||
arch = 'Win_x64' if os.name == 'nt' else 'Linux_x64'
|
||||
dl_file = 'chrome-win' if os.name == 'nt' else 'chrome-linux'
|
||||
dl_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, 'dist_chrome')
|
||||
@@ -60,7 +60,7 @@ def download_chromium():
|
||||
# Give executable permissions for *nix
|
||||
# file * | grep executable | cut -d: -f1
|
||||
print("Giving executable permissions...")
|
||||
execs = ['chrome', 'chrome_crashpad_handler', 'chrome_sandbox', 'chrome-wrapper', 'xdg-mime', 'xdg-settings']
|
||||
execs = ['chrome', 'chrome_crashpad_handler', 'chrome_sandbox', 'chrome-wrapper']
|
||||
for exec_file in execs:
|
||||
exec_path = os.path.join(chrome_path, exec_file)
|
||||
os.chmod(exec_path, 0o755)
|
||||
|
||||
@@ -90,6 +90,7 @@ if __name__ == "__main__":
|
||||
log_file = os.environ.get('LOG_FILE', None)
|
||||
log_html = utils.get_config_log_html()
|
||||
headless = utils.get_config_headless()
|
||||
browser_wait_timeout = utils.get_config_browser_wait_timeout()
|
||||
server_host = os.environ.get('HOST', '0.0.0.0')
|
||||
server_port = int(os.environ.get('PORT', 8191))
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ TURNSTILE_SELECTORS = [
|
||||
"input[name='cf-turnstile-response']"
|
||||
]
|
||||
|
||||
SHORT_TIMEOUT = 1
|
||||
SESSIONS_STORAGE = SessionsStorage()
|
||||
|
||||
|
||||
@@ -305,10 +304,16 @@ def _get_turnstile_token(driver: WebDriver, tabs: int):
|
||||
|
||||
# reset focus
|
||||
driver.execute_script("""
|
||||
let old = document.getElementById('__focus_helper');
|
||||
if (old) old.remove();
|
||||
|
||||
let el = document.createElement('button');
|
||||
el.style.position='fixed';
|
||||
el.style.top='0';
|
||||
el.style.left='0';
|
||||
el.id = '__focus_helper';
|
||||
el.style.position = 'fixed';
|
||||
el.style.top = '0';
|
||||
el.style.left = '0';
|
||||
el.style.opacity = '0.01';
|
||||
el.style.pointerEvents = 'none';
|
||||
document.body.prepend(el);
|
||||
el.focus();
|
||||
""")
|
||||
@@ -422,6 +427,7 @@ def _evil_logic(req: V1RequestBase, driver: WebDriver, method: str) -> Challenge
|
||||
logging.info("Challenge detected. Selector found: " + selector)
|
||||
break
|
||||
|
||||
browser_wait_timeout = utils.get_config_browser_wait_timeout()
|
||||
attempt = 0
|
||||
if challenge_found:
|
||||
while True:
|
||||
@@ -430,12 +436,12 @@ def _evil_logic(req: V1RequestBase, driver: WebDriver, method: str) -> Challenge
|
||||
# wait until the title changes
|
||||
for title in CHALLENGE_TITLES:
|
||||
logging.debug("Waiting for title (attempt " + str(attempt) + "): " + title)
|
||||
WebDriverWait(driver, SHORT_TIMEOUT).until_not(title_is(title))
|
||||
WebDriverWait(driver, browser_wait_timeout).until_not(title_is(title))
|
||||
|
||||
# then wait until all the selectors disappear
|
||||
for selector in CHALLENGE_SELECTORS:
|
||||
logging.debug("Waiting for selector (attempt " + str(attempt) + "): " + selector)
|
||||
WebDriverWait(driver, SHORT_TIMEOUT).until_not(
|
||||
WebDriverWait(driver, browser_wait_timeout).until_not(
|
||||
presence_of_element_located((By.CSS_SELECTOR, selector)))
|
||||
|
||||
# all elements not found
|
||||
@@ -453,7 +459,7 @@ def _evil_logic(req: V1RequestBase, driver: WebDriver, method: str) -> Challenge
|
||||
logging.debug("Waiting for redirect")
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
WebDriverWait(driver, SHORT_TIMEOUT).until(staleness_of(html_element))
|
||||
WebDriverWait(driver, browser_wait_timeout).until(staleness_of(html_element))
|
||||
except Exception:
|
||||
logging.debug("Timeout waiting for redirect")
|
||||
|
||||
@@ -466,7 +472,6 @@ def _evil_logic(req: V1RequestBase, driver: WebDriver, method: str) -> Challenge
|
||||
challenge_res = ChallengeResolutionResultT({})
|
||||
challenge_res.url = driver.current_url
|
||||
challenge_res.status = 200 # todo: fix, selenium not provides this info
|
||||
challenge_res.cookies = driver.get_cookies()
|
||||
challenge_res.userAgent = utils.get_user_agent(driver)
|
||||
challenge_res.turnstile_token = turnstile_token
|
||||
|
||||
@@ -482,6 +487,9 @@ def _evil_logic(req: V1RequestBase, driver: WebDriver, method: str) -> Challenge
|
||||
if req.returnScreenshot:
|
||||
challenge_res.screenshot = driver.get_screenshot_as_base64()
|
||||
|
||||
# Get cookies after all waits to capture cookies set during JavaScript execution
|
||||
challenge_res.cookies = driver.get_cookies()
|
||||
|
||||
res.result = challenge_res
|
||||
return res
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ class TestFlareSolverr(unittest.TestCase):
|
||||
'<title>Access denied</title>'),
|
||||
('badasstorrents', 'https://badasstorrents.com/torrents/search/720p/date/desc',
|
||||
'<title>Latest Torrents - BadassTorrents</title>'),
|
||||
('bt4g', 'https://bt4g.org/search/2022', '<title>Download 2022 Torrents - BT4G</title>'),
|
||||
('bt4g', 'https://bt4gprx.com/search?q=2022', '<title>Download 2022 Torrents - BT4G</title>'),
|
||||
('cinemaz', 'https://cinemaz.to/api/v1/jackett/torrents?in=1&type=0&search=',
|
||||
'<title>Access denied</title>'),
|
||||
('epublibre', 'https://epublibre.unblockit.cat/catalogo/index/0/nuevo/todos/sin/todos/--/ajax',
|
||||
|
||||
@@ -32,6 +32,10 @@ def get_config_disable_media() -> bool:
|
||||
return os.environ.get('DISABLE_MEDIA', 'false').lower() == 'true'
|
||||
|
||||
|
||||
def get_config_browser_wait_timeout() -> int:
|
||||
return int(os.environ.get('BROWSER_WAIT_TIMEOUT', 1))
|
||||
|
||||
|
||||
def get_flaresolverr_version() -> str:
|
||||
global FLARESOLVERR_VERSION
|
||||
if FLARESOLVERR_VERSION is not None:
|
||||
@@ -149,6 +153,8 @@ def get_webdriver(proxy: dict = None) -> WebDriver:
|
||||
options.add_argument('--disable-gpu-sandbox')
|
||||
options.add_argument('--ignore-certificate-errors')
|
||||
options.add_argument('--ignore-ssl-errors')
|
||||
# disable breaking popup
|
||||
options.add_argument("--disable-features=LocalNetworkAccessChecks")
|
||||
|
||||
language = os.environ.get('LANG', None)
|
||||
if language is not None:
|
||||
|
||||
Reference in New Issue
Block a user