Skip to content

Commit 17dae34

Browse files
committed
Add support for undetected-chromedriver as a subprocess
1 parent 152eaca commit 17dae34

File tree

6 files changed

+79
-15
lines changed

6 files changed

+79
-15
lines changed

help_docs/customizing_test_runs.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ pytest my_first_test.py --settings-file=custom_settings.py
162162
--enable-ws # (Enable Web Security on Chromium-based browsers.)
163163
--enable-sync # (Enable "Chrome Sync" on websites.)
164164
--use-auto-ext # (Use Chrome's automation extension.)
165-
--undetected | --uc # (Use undetected-chromedriver to evade bot-detection.)
165+
--uc | --undetected # (Use undetected-chromedriver to evade bot-detection.)
166+
--uc-sub | --uc-subprocess # (Use undetected-chromedriver as a subprocess.)
166167
--remote-debug # (Enable Chrome's Remote Debugger on http://localhost:9222)
167168
--final-debug # (Enter Debug Mode after each test ends. Don't use with CI!)
168169
--dashboard # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)

seleniumbase/behave/behave_sb.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@
7272
-D enable-ws (Enable Web Security on Chromium-based browsers.)
7373
-D enable-sync (Enable "Chrome Sync".)
7474
-D use-auto-ext (Use Chrome's automation extension.)
75-
-D undetected | -D uc (Use undetected-chromedriver to evade bot-detection)
75+
-D uc | -D undetected (Use undetected-chromedriver to evade bot-detection)
76+
-D uc-sub | -D uc-subprocess (Use undetected-chromedriver as a subprocess)
7677
-D remote-debug (Enable Chrome's Remote Debugger on http://localhost:9222)
7778
-D dashboard (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)
7879
-D dash-title=STRING (Set the title shown for the generated dashboard.)
@@ -169,6 +170,7 @@ def get_configured_sb(context):
169170
sb.enable_sync = False
170171
sb.use_auto_ext = False
171172
sb.undetectable = False
173+
sb.uc_subprocess = False
172174
sb.no_sandbox = False
173175
sb.disable_gpu = False
174176
sb._multithreaded = False
@@ -497,10 +499,15 @@ def get_configured_sb(context):
497499
if low_key in ["use-auto-ext", "use_auto_ext", "auto-ext"]:
498500
sb.use_auto_ext = True
499501
continue
500-
# Handle: -D use-auto-ext / use_auto_ext / auto-ext
502+
# Handle: -D undetected / undetectable / uc
501503
if low_key in ["undetected", "undetectable", "uc"]:
502504
sb.undetectable = True
503505
continue
506+
# Handle: -D uc-subprocess / uc_subprocess / uc-sub
507+
if low_key in ["uc-subprocess", "uc_subprocess", "uc-sub"]:
508+
sb.uc_subprocess = True
509+
sb.undetectable = True
510+
continue
504511
# Handle: -D no-sandbox / no_sandbox
505512
if low_key in ["no-sandbox", "no_sandbox"]:
506513
sb.no_sandbox = True
@@ -748,18 +755,17 @@ def get_configured_sb(context):
748755
if sb.recorder_ext and sb.headless:
749756
sb.headless = False
750757
sb.headless2 = True
751-
if sb.browser not in ["chrome", "edge"]:
758+
if sb.headless2 and sb.browser == "firefox":
759+
sb.headless2 = False # Only for Chromium browsers
760+
sb.headless = True # Firefox has regular headless
761+
elif sb.browser not in ["chrome", "edge"]:
752762
sb.headless2 = False # Only for Chromium browsers
753763
# Recorder Mode only supports Chromium browsers.
754764
if sb.recorder_ext and (sb.browser not in ["chrome", "edge"]):
755765
raise Exception(
756766
"\n\n Recorder Mode ONLY supports Chrome and Edge!"
757767
'\n (Your browser choice was: "%s")\n' % sb.browser
758768
)
759-
# Recorder Mode can still optimize scripts in --headless2 mode.
760-
if sb.recorder_mode and sb.headless:
761-
sb.headless = False
762-
sb.headless2 = True
763769
# The Xvfb virtual display server is for Linux OS Only.
764770
if sb.xvfb and "linux" not in sys.platform:
765771
sb.xvfb = False
@@ -778,6 +784,10 @@ def get_configured_sb(context):
778784
'or by calling the new "-D headless2".)'
779785
)
780786
sb.headless = True
787+
# Recorder Mode can still optimize scripts in --headless2 mode.
788+
if sb.recorder_mode and sb.headless:
789+
sb.headless = False
790+
sb.headless2 = True
781791
if not sb.headless and not sb.headless2:
782792
sb.headed = True
783793
if sb.servername != "localhost":

seleniumbase/core/browser_launcher.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ def _set_chrome_options(
354354
enable_sync,
355355
use_auto_ext,
356356
undetectable,
357+
uc_subprocess,
357358
no_sandbox,
358359
disable_gpu,
359360
headless2,
@@ -895,6 +896,7 @@ def get_driver(
895896
enable_sync=False,
896897
use_auto_ext=False,
897898
undetectable=False,
899+
uc_subprocess=False,
898900
no_sandbox=False,
899901
disable_gpu=False,
900902
headless2=False,
@@ -1046,6 +1048,7 @@ def get_driver(
10461048
enable_sync,
10471049
use_auto_ext,
10481050
undetectable,
1051+
uc_subprocess,
10491052
no_sandbox,
10501053
disable_gpu,
10511054
headless2,
@@ -1091,6 +1094,7 @@ def get_driver(
10911094
enable_sync,
10921095
use_auto_ext,
10931096
undetectable,
1097+
uc_subprocess,
10941098
no_sandbox,
10951099
disable_gpu,
10961100
headless2,
@@ -1140,6 +1144,7 @@ def get_remote_driver(
11401144
enable_sync,
11411145
use_auto_ext,
11421146
undetectable,
1147+
uc_subprocess,
11431148
no_sandbox,
11441149
disable_gpu,
11451150
headless2,
@@ -1239,6 +1244,7 @@ def get_remote_driver(
12391244
enable_sync,
12401245
use_auto_ext,
12411246
undetectable,
1247+
uc_subprocess,
12421248
no_sandbox,
12431249
disable_gpu,
12441250
headless2,
@@ -1467,6 +1473,7 @@ def get_remote_driver(
14671473
enable_sync,
14681474
use_auto_ext,
14691475
undetectable,
1476+
uc_subprocess,
14701477
no_sandbox,
14711478
disable_gpu,
14721479
headless2,
@@ -1661,6 +1668,7 @@ def get_local_driver(
16611668
enable_sync,
16621669
use_auto_ext,
16631670
undetectable,
1671+
uc_subprocess,
16641672
no_sandbox,
16651673
disable_gpu,
16661674
headless2,
@@ -2260,6 +2268,7 @@ def get_local_driver(
22602268
enable_sync,
22612269
use_auto_ext,
22622270
undetectable,
2271+
uc_subprocess,
22632272
no_sandbox,
22642273
disable_gpu,
22652274
headless2,
@@ -2322,6 +2331,7 @@ def get_local_driver(
23222331
enable_sync,
23232332
use_auto_ext,
23242333
undetectable,
2334+
uc_subprocess,
23252335
no_sandbox,
23262336
disable_gpu,
23272337
headless2,
@@ -2592,6 +2602,7 @@ def get_local_driver(
25922602
driver_executable_path=uc_path,
25932603
headless=False, # Xvfb needed!
25942604
version_main=uc_chrome_version,
2605+
use_subprocess=uc_subprocess,
25952606
)
25962607
except URLError as e:
25972608
if (
@@ -2609,6 +2620,7 @@ def get_local_driver(
26092620
driver_executable_path=uc_path,
26102621
headless=False, # Xvfb needed!
26112622
version_main=uc_chrome_version,
2623+
use_subprocess=uc_subprocess,
26122624
)
26132625
else:
26142626
raise
@@ -2700,6 +2712,7 @@ def get_local_driver(
27002712
enable_sync,
27012713
use_auto_ext,
27022714
undetectable,
2715+
uc_subprocess,
27032716
no_sandbox,
27042717
disable_gpu,
27052718
headless2,

seleniumbase/fixtures/base_case.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,6 +3181,7 @@ def get_new_driver(
31813181
enable_sync=None,
31823182
use_auto_ext=None,
31833183
undetectable=None,
3184+
uc_subprocess=None,
31843185
no_sandbox=None,
31853186
disable_gpu=None,
31863187
headless2=None,
@@ -3229,6 +3230,7 @@ def get_new_driver(
32293230
enable_sync - the option to enable the Chrome Sync feature (Chrome)
32303231
use_auto_ext - the option to enable Chrome's Automation Extension
32313232
undetectable - the option to use an undetectable chromedriver
3233+
uc_subprocess - use the undetectable chromedriver as a subprocess
32323234
no_sandbox - the option to enable the "No-Sandbox" feature (Chrome)
32333235
disable_gpu - the option to enable Chrome's "Disable GPU" feature
32343236
headless2 - the option to use the newer headless mode (Chromium)
@@ -3323,6 +3325,8 @@ def get_new_driver(
33233325
use_auto_ext = self.use_auto_ext
33243326
if undetectable is None:
33253327
undetectable = self.undetectable
3328+
if uc_subprocess is None:
3329+
uc_subprocess = self.uc_subprocess
33263330
if no_sandbox is None:
33273331
no_sandbox = self.no_sandbox
33283332
if disable_gpu is None:
@@ -3404,6 +3408,7 @@ def get_new_driver(
34043408
enable_sync=enable_sync,
34053409
use_auto_ext=use_auto_ext,
34063410
undetectable=undetectable,
3411+
uc_subprocess=uc_subprocess,
34073412
no_sandbox=no_sandbox,
34083413
disable_gpu=disable_gpu,
34093414
headless2=headless2,
@@ -12545,6 +12550,7 @@ def __activate_virtual_display_as_needed(self):
1254512550
self.display = Display(visible=0, size=(width, height))
1254612551
self.display.start()
1254712552
self.headless_active = True
12553+
sb_config.headless_active = True
1254812554
except Exception:
1254912555
pass
1255012556

@@ -12630,6 +12636,7 @@ def setUp(self, masterqa_mode=False):
1263012636
self.with_selenium = sb_config.with_selenium # Should be True
1263112637
self.headless = sb_config.headless
1263212638
self.headless_active = False
12639+
sb_config.headless_active = False
1263312640
self.headed = sb_config.headed
1263412641
self.xvfb = sb_config.xvfb
1263512642
self.locale_code = sb_config.locale_code
@@ -12687,6 +12694,7 @@ def setUp(self, masterqa_mode=False):
1268712694
self.enable_sync = sb_config.enable_sync
1268812695
self.use_auto_ext = sb_config.use_auto_ext
1268912696
self.undetectable = sb_config.undetectable
12697+
self.uc_subprocess = sb_config.uc_subprocess
1269012698
self.no_sandbox = sb_config.no_sandbox
1269112699
self.disable_gpu = sb_config.disable_gpu
1269212700
self.headless2 = sb_config.headless2
@@ -12978,6 +12986,7 @@ def setUp(self, masterqa_mode=False):
1297812986
enable_sync=self.enable_sync,
1297912987
use_auto_ext=self.use_auto_ext,
1298012988
undetectable=self.undetectable,
12989+
uc_subprocess=self.uc_subprocess,
1298112990
no_sandbox=self.no_sandbox,
1298212991
disable_gpu=self.disable_gpu,
1298312992
headless2=self.headless2,

seleniumbase/plugins/pytest_plugin.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ def pytest_addoption(parser):
9090
--enable-ws (Enable Web Security on Chromium-based browsers.)
9191
--enable-sync (Enable "Chrome Sync" on websites.)
9292
--use-auto-ext (Use Chrome's automation extension.)
93-
--undetected | --uc (Use undetected-chromedriver to evade bot-detection.)
93+
--uc | --undetected (Use undetected-chromedriver to evade bot-detection.)
94+
--uc-sub | --uc-subprocess (Use undetected-chromedriver as a subprocess.)
9495
--remote-debug (Enable Chrome's Remote Debugger on http://localhost:9222)
9596
--final-debug (Enter Debug Mode after each test ends. Don't use with CI!)
9697
--dashboard (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)
@@ -910,6 +911,17 @@ def pytest_addoption(parser):
910911
to websites that use anti-bot services to block
911912
automation tools from navigating them freely.""",
912913
)
914+
parser.addoption(
915+
"--uc_subprocess",
916+
"--uc-subprocess",
917+
"--uc-sub", # undetected-chromedriver subprocess mode
918+
action="store_true",
919+
dest="uc_subprocess",
920+
default=False,
921+
help="""Use undetectable-chromedriver as a subprocess,
922+
which can help avoid issues that might result.
923+
It may reduce UC's ability to avoid detection.""",
924+
)
913925
parser.addoption(
914926
"--no_sandbox",
915927
"--no-sandbox",
@@ -1252,6 +1264,9 @@ def pytest_addoption(parser):
12521264
"--undetected" in sys_argv
12531265
or "--undetectable" in sys_argv
12541266
or "--uc" in sys_argv
1267+
or "--uc-subprocess" in sys_argv
1268+
or "--uc_subprocess" in sys_argv
1269+
or "--uc-sub" in sys_argv
12551270
)
12561271
):
12571272
message = (
@@ -1363,6 +1378,9 @@ def pytest_configure(config):
13631378
sb_config.enable_sync = config.getoption("enable_sync")
13641379
sb_config.use_auto_ext = config.getoption("use_auto_ext")
13651380
sb_config.undetectable = config.getoption("undetectable")
1381+
sb_config.uc_subprocess = config.getoption("uc_subprocess")
1382+
if sb_config.uc_subprocess and not sb_config.undetectable:
1383+
sb_config.undetectable = True
13661384
sb_config.no_sandbox = config.getoption("no_sandbox")
13671385
sb_config.disable_gpu = config.getoption("disable_gpu")
13681386
sb_config.remote_debug = config.getoption("remote_debug")
@@ -1457,11 +1475,6 @@ def pytest_configure(config):
14571475
sb_config.recorder_mode = False
14581476
sb_config.recorder_ext = False
14591477

1460-
# Recorder Mode can still optimize scripts in --headless2 mode.
1461-
if sb_config.recorder_mode and sb_config.headless:
1462-
sb_config.headless = False
1463-
sb_config.headless2 = True
1464-
14651478
if sb_config.xvfb and "linux" not in sys.platform:
14661479
# The Xvfb virtual display server is for Linux OS Only!
14671480
sb_config.xvfb = False
@@ -1480,6 +1493,12 @@ def pytest_configure(config):
14801493
"or by calling the new --headless2.)"
14811494
)
14821495
sb_config.headless = True
1496+
1497+
# Recorder Mode can still optimize scripts in --headless2 mode.
1498+
if sb_config.recorder_mode and sb_config.headless:
1499+
sb_config.headless = False
1500+
sb_config.headless2 = True
1501+
14831502
if not sb_config.headless and not sb_config.headless2:
14841503
sb_config.headed = True
14851504

seleniumbase/plugins/selenium_plugin.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ class SeleniumBrowser(Plugin):
6868
--enable-ws (Enable Web Security on Chromium-based browsers.)
6969
--enable-sync (Enable "Chrome Sync" on websites.)
7070
--use-auto-ext (Use Chrome's automation extension.)
71-
--undetected | --uc (Use undetected-chromedriver to evade bot-detection.)
71+
--uc | --undetected (Use undetected-chromedriver to evade bot-detection.)
72+
--uc-sub | --uc-subprocess (Use undetected-chromedriver as a subprocess.)
7273
--remote-debug (Enable Chrome's Remote Debugger on http://localhost:9222)
7374
--final-debug (Enter Debug Mode after each test ends. Don't use with CI!)
7475
--swiftshader (Use Chrome's "--use-gl=swiftshader" feature.)
@@ -634,6 +635,17 @@ def options(self, parser, env):
634635
to websites that use anti-bot services to block
635636
automation tools from navigating them freely.""",
636637
)
638+
parser.add_option(
639+
"--uc_subprocess",
640+
"--uc-subprocess",
641+
"--uc-sub", # undetected-chromedriver subprocess mode
642+
action="store_true",
643+
dest="uc_subprocess",
644+
default=False,
645+
help="""Use undetectable-chromedriver as a subprocess,
646+
which can help avoid issues that might result.
647+
It may reduce UC's ability to avoid detection.""",
648+
)
637649
parser.add_option(
638650
"--no_sandbox",
639651
"--no-sandbox",

0 commit comments

Comments
 (0)