Pydoll is a library for automating chromium-based browsers without a WebDriver, offering realistic interactions.
This report presents the forensic synthetic code analysis of autoscrape-labs/pydoll, a HTML project with 7,053 GitHub stars. SynthScan v2.0 examined 90,437 lines of code across 478 source files, recording 1159 pattern matches distributed across 17 syntactic categories. The overall adjusted score of 17.8 places this repository in the Moderate AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 1159 distinct pattern matches across 17 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/unit/test_har_recorder.py | 33 | async def test_stop_awaits_in_flight_body_tasks_and_cleans_up(): | CODE |
| LOW | tests/unit/test_har_recorder.py | 56 | async def test_stop_flushes_in_flight_request_as_pending_entry(): | CODE |
| LOW | tests/unit/test_har_recorder.py | 94 | async def test_fetch_response_body_retries_until_body_available(): | CODE |
| LOW | tests/unit/test_har_recorder.py | 107 | async def test_fetch_response_body_no_retry_when_body_not_expected(): | CODE |
| LOW | tests/unit/test_har_recorder.py | 119 | async def test_fetch_response_body_gives_up_after_max_attempts(): | CODE |
| LOW | tests/unit/test_emulation_commands.py | 13 | def test_get_screen_infos_shape(): | CODE |
| LOW | tests/unit/test_emulation_commands.py | 41 | def test_update_screen_omits_unset_params(): | CODE |
| LOW | tests/unit/test_emulation_commands.py | 46 | def test_update_screen_requires_only_screen_id(): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 24 | def test_normalize_synthetic_xpath_extracts_inner_xpath(): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 28 | def test_normalize_synthetic_xpath_passes_through_plain_selector(): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 32 | def test_normalize_synthetic_xpath_returns_input_when_unparseable(): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 43 | def test_decode_image_to_bytes(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 52 | def test_decode_image_to_bytes_empty_string(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 59 | def test_decode_image_to_bytes_complex_data(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 210 | def test_validate_browser_paths_file_exists_but_not_executable(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 226 | def test_validate_browser_paths_directory_instead_of_file(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 236 | def test_validate_browser_paths_empty_list(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 245 | def test_validate_browser_paths_mixed_valid_invalid(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 287 | def test_validate_browser_paths_valid_path(self, tmp_path): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 297 | def test_validate_browser_paths_invalid_paths(self): | CODE |
| LOW | tests/unit/test_utils.py | 105 | async def test_missing_websocket_url(self): | CODE |
| LOW | tests/unit/test_utils.py | 155 | def test_validate_browser_paths_success(self): | CODE |
| LOW | tests/unit/test_utils.py | 173 | def test_validate_browser_paths_first_valid_wins(self): | CODE |
| LOW | tests/unit/test_utils.py | 192 | def test_validate_browser_paths_no_valid_paths(self): | CODE |
| LOW | tests/unit/test_utils.py | 308 | def test_clean_script_for_analysis_removes_comments(self): | CODE |
| LOW⚡ | tests/unit/test_utils.py | 340 | def test_is_script_already_function_regular_function(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 345 | def test_is_script_already_function_arrow_function(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 350 | def test_is_script_already_function_with_parameters(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 355 | def test_is_script_already_function_not_function(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 360 | def test_is_script_already_function_with_whitespace(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 365 | def test_has_return_outside_function_simple_return(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 370 | def test_has_return_outside_function_no_return(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 375 | def test_has_return_outside_function_return_inside_function(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 385 | def test_has_return_outside_function_mixed_returns(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 395 | def test_has_return_outside_function_already_function(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 400 | def test_has_return_outside_function_with_comments(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 410 | def test_has_return_outside_function_nested_braces(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 424 | def test_has_return_outside_function_arrow_function(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 434 | def test_extract_text_without_strip_without_separator(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 440 | def test_extract_text_with_strip_without_separator(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 446 | def test_extract_text_without_strip_with_separator(self): | STRING |
| LOW⚡ | tests/unit/test_utils.py | 452 | def test_extract_text_with_strip_with_separator(self): | STRING |
| LOW | tests/unit/test_utils.py | 324 | def test_clean_script_for_analysis_removes_strings(self): | STRING |
| LOW | tests/unit/test_keyboard_humanized.py | 67 | async def test_humanized_typing_without_typos_reproduces_text(field, monkeypatch): | CODE |
| LOW⚡ | tests/unit/test_keyboard_humanized.py | 88 | async def test_each_typo_type_self_corrects_to_intended_text( | CODE |
| LOW⚡ | tests/unit/test_keyboard_humanized.py | 96 | async def test_adjacent_typo_on_non_qwerty_char_still_yields_char(field, force_typos): | CODE |
| LOW⚡ | tests/unit/test_keyboard_humanized.py | 102 | async def test_transpose_typo_without_alpha_neighbor_still_yields_text(field, force_typos): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 32 | async def test_mouse_click_presses_and_releases_at_target(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 40 | async def test_mouse_move_positions_cursor_at_target(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 46 | async def test_mouse_down_presses_and_up_releases(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 54 | async def test_double_click_uses_click_count_two(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 60 | async def test_drag_presses_at_start_and_releases_at_end(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 68 | async def test_keyboard_down_then_up_for_a_key(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 76 | async def test_keyboard_press_presses_and_releases_the_key(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 83 | async def test_keyboard_type_text_types_each_character_in_order(fake_conn, fake_tab): | CODE |
| LOW | tests/unit/test_interactions.py | 98 | async def test_hotkey_applies_combined_modifier_to_key(fake_conn, fake_tab, keys, expected_modifier): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 109 | async def test_hotkey_without_modifier_keys_sends_no_modifier(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 116 | async def test_scroll_by_issues_scroll_with_distance(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 124 | async def test_scroll_to_top_issues_a_scroll(fake_conn, fake_tab): | CODE |
| LOW⚡ | tests/unit/test_interactions.py | 130 | async def test_scroll_to_bottom_issues_a_scroll(fake_conn, fake_tab): | CODE |
| 726 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/integration/test_iframe_integration.py | 1136 | Its ``contentDocument.frameId`` is null, so resolution goes through the | STRING |
| HIGH | pydoll/constants.py | 31 | rect.width > 0 && rect.height > 0 | CODE |
| HIGH | pydoll/constants.py | 47 | return elementFromPoint === this || this.contains(elementFromPoint); | CODE |
| HIGH | pydoll/constants.py | 90 | var select = this && this.parentElement ? this.parentElement.closest('select') : null; | CODE |
| HIGH | pydoll/constants.py | 90 | var select = this && this.parentElement ? this.parentElement.closest('select') : null; | CODE |
| HIGH⚡ | pydoll/constants.py | 112 | "{escaped_value}", this, null, | CODE |
| HIGH⚡ | pydoll/constants.py | 120 | "{escaped_value}", document, null, | CODE |
| HIGH⚡ | pydoll/constants.py | 129 | "{escaped_value}", this, null, | CODE |
| HIGH⚡ | pydoll/constants.py | 134 | results.push(elements.snapshotItem(i)); | CODE |
| HIGH⚡ | pydoll/constants.py | 142 | "{escaped_value}", document, null, | CODE |
| HIGH⚡ | pydoll/constants.py | 147 | results.push(elements.snapshotItem(i)); | CODE |
| HIGH | pydoll/constants.py | 173 | null, | CODE |
| HIGH | pydoll/constants.py | 209 | allDescendants.push( | CODE |
| HIGH | pydoll/constants.py | 276 | jsonData = null; | CODE |
| HIGH | pydoll/constants.py | 280 | jsonData = null; | CODE |
| HIGH | pydoll/constants.py | 295 | error: error.toString(), | CODE |
| HIGH | pydoll/constants.py | 388 | GET_SCROLL_Y = 'window.scrollY || window.pageYOffset || 0' | STRING |
| HIGH | pydoll/constants.py | 397 | const scrollTop = window.scrollY || window.pageYOffset || 0; | CODE |
| HIGH | pydoll/constants.py | 426 | if (!hasSelection && text === '') { | CODE |
| HIGH | pydoll/constants.py | 512 | return !!(this && this.tagName && this.tagName.toLowerCase() === 'option'); | CODE |
| HIGH | pydoll/utils/fingerprint_builder.py | 14 | - ``Object.getOwnPropertyDescriptor(proto, prop).get.toString()`` must | STRING |
| HIGH | pydoll/utils/fingerprint_builder.py | 99 | const _og = _od && _od.get; | CODE |
| HIGH | pydoll/utils/fingerprint_builder.py | 346 | if (paramOverrides[pname] !== undefined) return paramOverrides[pname]; | CODE |
| HIGH | pydoll/utils/fingerprint_builder.py | 363 | if (extOverrides !== null) { | CODE |
| HIGH | pydoll/utils/fingerprint_builder.py | 366 | if (!extOverrides.includes(name)) return null; | CODE |
| HIGH⚡ | pydoll/utils/fingerprint_builder.py | 507 | for (let i = 0; i < {audio_in}; i++) devices.push(makeDev('audioinput')); | CODE |
| HIGH⚡ | pydoll/utils/fingerprint_builder.py | 508 | for (let i = 0; i < {audio_out}; i++) devices.push(makeDev('audiooutput')); | CODE |
| HIGH⚡ | pydoll/utils/fingerprint_builder.py | 509 | for (let i = 0; i < {video_in}; i++) devices.push(makeDev('videoinput')); | CODE |
| HIGH⚡ | pydoll/utils/fingerprint_builder.py | 671 | ' const name = desc && desc.name;\n' | CODE |
| HIGH⚡ | pydoll/utils/fingerprint_builder.py | 672 | ' if (name && overrides[name] !== undefined) {\n' | CODE |
| HIGH⚡ | pydoll/utils/fingerprint_builder.py | 672 | ' if (name && overrides[name] !== undefined) {\n' | CODE |
| HIGH⚡ | pydoll/utils/fingerprint_builder.py | 676 | ' onchange: null,\n' | CODE |
| HIGH | pydoll/protocol/fingerprint/types.py | 307 | do_not_track: NotRequired[str] # navigator.doNotTrack (null, "1") | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | pydoll/connection/connection_handler.py | 96 | Send CDP command and await response. Args: command: CDP command to send. timeo | STRING |
| HIGH | pydoll/utils/general.py | 159 | Validates potential browser executable paths and returns the first valid one. Checks a list of possible browse | STRING |
| HIGH | pydoll/extractor/field.py | 64 | Define extraction metadata for a model field. Wraps pydantic.Field() and registers ExtractionMetadata for the engin | STRING |
| HIGH | pydoll/extractor/model.py | 62 | Read ExtractionMetadata from pydantic FieldInfo objects via registry. For each field, checks if json_schema_extra c | STRING |
| HIGH | pydoll/extractor/engine.py | 42 | Extract a single model instance from the page. Args: model: ExtractionModel subclass to populate. | STRING |
| HIGH | pydoll/extractor/engine.py | 294 | Build model instance from extracted values. Pydantic handles validation, type coercion, and defaults. Args: | STRING |
| HIGH | pydoll/browser/tab.py | 288 | Extract structured data from the page into a typed model. Args: model: ExtractionModel subclass def | STRING |
| HIGH | pydoll/browser/tab.py | 550 | .. deprecated:: ?.?.? Use iframe `WebElement` instances directly; this method will be removed in | STRING |
| HIGH | pydoll/browser/tab.py | 603 | Find all shadow roots in the page. Traverses the entire DOM tree (including iframes and nested shadow | STRING |
| HIGH | pydoll/browser/tab.py | 901 | Get the response body for a given request ID. Args: request_id: Request ID to get the resp | STRING |
| HIGH | pydoll/browser/tab.py | 923 | Get network logs. Args: filter: Filter to apply to the network logs. Returns: | STRING |
| HIGH | pydoll/browser/tab.py | 1047 | Capture screenshot of current page. Args: path: File path for screenshot (extension determ | STRING |
| HIGH | pydoll/browser/tab.py | 1127 | Generate PDF of current page. Args: path: File path for PDF output. Required if as_base64= | STRING |
| HIGH | pydoll/browser/tab.py | 1387 | Execute JavaScript in page context. Args: script (str): JavaScript code to execute. | STRING |
| HIGH | pydoll/browser/requests/request.py | 108 | Execute an HTTP request in the browser's JavaScript context. This method uses the browser's fetch API to make r | STRING |
| HIGH | pydoll/browser/chromium/base.py | 177 | Start browser process and establish CDP connection. Args: headless: Deprecated. Use `optio | STRING |
| HIGH | pydoll/elements/web_element.py | 288 | Get the shadow root attached to this element. Args: timeout: Maximum seconds to wait for t | STRING |
| HIGH | pydoll/elements/web_element.py | 354 | Retrieve all direct and nested child elements of this element. Args: max_depth (int, optio | STRING |
| HIGH | pydoll/elements/web_element.py | 385 | Retrieve all sibling elements of this element (elements at the same DOM level). Args: tag_ | STRING |
| HIGH | pydoll/elements/web_element.py | 415 | Capture screenshot of this element only. Automatically scrolls element into view before capturing. | STRING |
| HIGH | pydoll/elements/web_element.py | 873 | Execute JavaScript in element context. Args: script (str): JavaScript code to execute. Use | STRING |
| HIGH | pydoll/elements/mixins/find_elements_mixin.py | 152 | Find element(s) using combination of common HTML attributes. Flexible element location using standard | STRING |
| HIGH | pydoll/elements/mixins/find_elements_mixin.py | 257 | Find element(s) using raw CSS selector or XPath expression. Direct access using CSS or XPath syntax. S | STRING |
| HIGH | pydoll/elements/mixins/find_elements_mixin.py | 300 | Core element finding method with optional waiting capability. Searches for elements with flexible wait | STRING |
| HIGH | pydoll/elements/mixins/find_elements_mixin.py | 370 | Retry loop for iframe-crossing element searches. Repeatedly calls :meth:`_attempt_find_across_iframes` | STRING |
| HIGH | pydoll/elements/mixins/find_elements_mixin.py | 450 | Find first element matching selector. Internal method performing actual element search. Can be called | STRING |
| HIGH | pydoll/elements/mixins/find_elements_mixin.py | 513 | Find all elements matching selector. Internal method performing actual multi-element search. Can be ca | STRING |
| HIGH | pydoll/commands/network_commands.py | 140 | Deletes browser cookies with matching criteria. Provides granular control over cookie removal through | STRING |
| HIGH | pydoll/commands/network_commands.py | 224 | Retrieves cookies matching specified URLs. Args: urls: list of URLs to scope cookie retrie | STRING |
| HIGH | pydoll/commands/network_commands.py | 430 | Applies custom HTTP headers to all subsequent requests. Enables advanced scenarios: - A/B test | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/unit/test_har_recorder.py | 9 | CODE | |
| LOW | tests/unit/test_emulation_commands.py | 7 | CODE | |
| LOW | tests/unit/test_utils.py | 7 | CODE | |
| LOW | tests/unit/conftest.py | 11 | CODE | |
| LOW | tests/unit/test_keyboard_humanized.py | 14 | CODE | |
| LOW | tests/unit/test_interactions.py | 8 | CODE | |
| LOW | tests/unit/test_shadow_root.py | 9 | CODE | |
| LOW | tests/unit/test_decorators.py | 5 | CODE | |
| LOW | tests/unit/test_decorators.py | 6 | CODE | |
| LOW | tests/unit/test_extractor_helpers.py | 3 | CODE | |
| LOW | tests/unit/test_temp_dir_manager.py | 8 | CODE | |
| LOW | tests/unit/test_interactions_utils.py | 3 | CODE | |
| LOW | tests/unit/test_har_cookie_parsing.py | 11 | CODE | |
| LOW | tests/unit/test_web_element.py | 10 | CODE | |
| LOW | tests/unit/test_browser_wiring.py | 8 | CODE | |
| LOW | tests/unit/test_browser_commands.py | 9 | CODE | |
| LOW | tests/unit/test_selector_parser.py | 3 | CODE | |
| LOW | tests/unit/test_user_agent_parser.py | 8 | CODE | |
| LOW | tests/unit/test_fingerprint_applier.py | 8 | CODE | |
| LOW | tests/unit/test_proxy_manager.py | 7 | CODE | |
| LOW | tests/unit/test_commands_manager.py | 3 | CODE | |
| LOW | tests/unit/test_bundle.py | 10 | CODE | |
| LOW | tests/unit/test_fingerprint_builder.py | 9 | CODE | |
| LOW | tests/unit/test_events_manager.py | 3 | CODE | |
| LOW | tests/unit/test_mouse_humanized.py | 12 | CODE | |
| LOW | tests/unit/test_tab_commands.py | 10 | CODE | |
| LOW | tests/unit/test_request_cookie_extraction.py | 11 | CODE | |
| LOW | tests/unit/test_scroll_humanized.py | 15 | CODE | |
| LOW | tests/unit/test_find_elements_mixin.py | 9 | CODE | |
| LOW | tests/integration/conftest.py | 3 | CODE | |
| LOW | tests/integration/test_web_element_integration.py | 10 | CODE | |
| LOW | tests/integration/test_web_element_integration.py | 19 | CODE | |
| LOW | tests/integration/test_tab_io_integration.py | 12 | CODE | |
| LOW | tests/integration/test_tab_io_integration.py | 20 | CODE | |
| LOW | tests/integration/test_extractor_integration.py | 3 | CODE | |
| LOW | tests/integration/test_interactions_integration.py | 9 | CODE | |
| LOW | tests/integration/test_tab_request_integration.py | 9 | CODE | |
| LOW | tests/integration/test_tab_features_integration.py | 11 | CODE | |
| LOW | tests/integration/test_tab.py | 10 | CODE | |
| LOW | tests/integration/test_browser_integration.py | 10 | CODE | |
| LOW | tests/integration/test_socks5_forwarder.py | 13 | CODE | |
| LOW | tests/integration/test_connection_handler.py | 9 | CODE | |
| LOW | tests/integration/_waits.py | 10 | CODE | |
| LOW | pydoll/interactions/scroll.py | 1 | CODE | |
| LOW | pydoll/interactions/__init__.py | 1 | CODE | |
| LOW | pydoll/interactions/__init__.py | 1 | CODE | |
| LOW | pydoll/interactions/__init__.py | 2 | CODE | |
| LOW | pydoll/interactions/__init__.py | 2 | CODE | |
| LOW | pydoll/interactions/__init__.py | 3 | CODE | |
| LOW | pydoll/interactions/__init__.py | 3 | CODE | |
| LOW | pydoll/interactions/__init__.py | 3 | CODE | |
| LOW | pydoll/interactions/__init__.py | 3 | CODE | |
| LOW | pydoll/interactions/__init__.py | 3 | CODE | |
| LOW | pydoll/interactions/__init__.py | 10 | CODE | |
| LOW | pydoll/interactions/__init__.py | 10 | CODE | |
| LOW | pydoll/interactions/__init__.py | 10 | CODE | |
| LOW | pydoll/interactions/__init__.py | 11 | CODE | |
| LOW | pydoll/interactions/__init__.py | 11 | CODE | |
| LOW | pydoll/interactions/__init__.py | 11 | CODE | |
| LOW | pydoll/interactions/iframe.py | 1 | CODE | |
| 98 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/integration/test_extractor_integration.py | 208 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/integration/test_extractor_integration.py | 210 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_extractor_integration.py | 22 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_extractor_integration.py | 24 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 21 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 23 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 160 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 162 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 198 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 200 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 235 | # ================================================================== | COMMENT |
| MEDIUM⚡ | pydoll/elements/utils/selector_parser.py | 237 | # ================================================================== | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 49 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 51 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 66 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 68 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 113 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 115 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 126 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM | pydoll/elements/utils/selector_parser.py | 128 | # ------------------------------------------------------------------ | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/unit/conftest.py | 39 | def set_response(self, method: str, result: dict) -> None: | CODE |
| LOW | tests/integration/conftest.py | 75 | def set_result(self, method: str, result: dict) -> None: | CODE |
| LOW | pydoll/decorators.py | 7 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/interactions/__init__.py | 13 | __all__ = [ | CODE |
| LOW | pydoll/interactions/iframe.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/interactions/mouse.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/interactions/keyboard.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/connection/connection_handler.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/connection/__init__.py | 3 | __all__ = [ | CODE |
| LOW | pydoll/connection/managers/events_manager.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/connection/managers/__init__.py | 4 | __all__ = [ | CODE |
| LOW | pydoll/connection/managers/commands_manager.py | 10 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/utils/socks5_proxy_forwarder.py | 66 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/utils/__init__.py | 15 | __all__ = [ | CODE |
| LOW | pydoll/utils/general.py | 13 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/extractor/__init__.py | 9 | __all__ = [ | CODE |
| LOW | pydoll/extractor/engine.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/fingerprint_applier.py | 42 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/__init__.py | 4 | __all__ = ['Chrome', 'Edge'] | CODE |
| LOW | pydoll/browser/tab.py | 131 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/managers/browser_process_manager.py | 5 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/managers/proxy_manager.py | 9 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/managers/proxy_manager.py | 105 | def _update_proxy_argument(self, index: int, clean_proxy: str) -> None: | CODE |
| LOW | pydoll/browser/managers/__init__.py | 10 | __all__ = [ | CODE |
| LOW | pydoll/browser/managers/browser_options_manager.py | 13 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/managers/temp_dir_manager.py | 9 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/requests/request.py | 31 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/requests/__init__.py | 10 | __all__ = ['HarCapture', 'Request', 'Response'] | CODE |
| LOW | pydoll/browser/requests/response.py | 13 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/requests/har_recorder.py | 53 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/chromium/edge.py | 15 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/chromium/__init__.py | 4 | __all__ = [ | CODE |
| LOW | pydoll/browser/chromium/chrome.py | 15 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/chromium/base.py | 77 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/browser/chromium/base.py | 832 | async def _setup_worker_user_agent_override(self) -> None: | CODE |
| LOW | pydoll/elements/shadow_root.py | 15 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/elements/web_element.py | 73 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/elements/mixins/__init__.py | 3 | __all__ = [ | CODE |
| LOW | pydoll/elements/mixins/find_elements_mixin.py | 33 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/elements/utils/__init__.py | 3 | __all__ = ['SelectorParser'] | CODE |
| LOW⚡ | pydoll/elements/utils/selector_parser.py | 19 | logger = logging.getLogger(__name__) | CODE |
| LOW | pydoll/commands/__init__.py | 14 | __all__ = [ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docs/pt/deep-dive/network/build-proxy.md | 71 | except Exception as e: | CODE |
| LOW | docs/pt/deep-dive/network/build-proxy.md | 100 | except Exception: | CODE |
| LOW | docs/pt/deep-dive/network/build-proxy.md | 265 | except Exception as e: | CODE |
| MEDIUM | docs/pt/deep-dive/network/build-proxy.md | 41 | def _handle_client(self, reader, writer): | CODE |
| MEDIUM | docs/pt/deep-dive/network/build-proxy.md | 256 | def _handle_client(self, reader, writer): | CODE |
| LOW | docs/zh/deep-dive/network/build-proxy.md | 71 | except Exception as e: | CODE |
| LOW | docs/zh/deep-dive/network/build-proxy.md | 100 | except Exception: | CODE |
| LOW | docs/zh/deep-dive/network/build-proxy.md | 265 | except Exception as e: | CODE |
| MEDIUM | docs/zh/deep-dive/network/build-proxy.md | 41 | def _handle_client(self, reader, writer): | CODE |
| MEDIUM | docs/zh/deep-dive/network/build-proxy.md | 256 | def _handle_client(self, reader, writer): | CODE |
| LOW | docs/en/deep-dive/network/build-proxy.md | 71 | except Exception as e: | CODE |
| LOW | docs/en/deep-dive/network/build-proxy.md | 100 | except Exception: | CODE |
| LOW | docs/en/deep-dive/network/build-proxy.md | 265 | except Exception as e: | CODE |
| MEDIUM | docs/en/deep-dive/network/build-proxy.md | 41 | def _handle_client(self, reader, writer): | CODE |
| MEDIUM | docs/en/deep-dive/network/build-proxy.md | 256 | def _handle_client(self, reader, writer): | CODE |
| LOW | pydoll/decorators.py | 47 | except Exception as e_inner: | CODE |
| LOW | pydoll/decorators.py | 50 | except Exception as e: | CODE |
| LOW | pydoll/decorators.py | 118 | except Exception as exc: | CODE |
| LOW | pydoll/interactions/iframe.py | 294 | except Exception: | CODE |
| LOW | pydoll/connection/connection_handler.py | 271 | except Exception: | CODE |
| LOW | pydoll/connection/connection_handler.py | 275 | except Exception: | CODE |
| LOW | pydoll/connection/managers/events_manager.py | 92 | except Exception: | CODE |
| LOW | pydoll/connection/managers/events_manager.py | 182 | except Exception as e: | CODE |
| LOW | pydoll/utils/socks5_proxy_forwarder.py | 279 | except Exception: | CODE |
| LOW | pydoll/extractor/engine.py | 310 | except Exception as exc: | CODE |
| LOW | pydoll/browser/tab.py | 1239 | except Exception: | CODE |
| LOW | pydoll/browser/tab.py | 2058 | except Exception as exc: | CODE |
| LOW | pydoll/browser/managers/temp_dir_manager.py | 144 | except Exception: # noqa: BLE001 - best-effort cleanup | CODE |
| LOW | pydoll/browser/requests/request.py | 151 | except Exception as exc: | CODE |
| LOW | pydoll/browser/requests/har_recorder.py | 65 | except Exception: | CODE |
| LOW | pydoll/browser/requests/har_recorder.py | 331 | except Exception: | CODE |
| LOW | pydoll/browser/requests/har_recorder.py | 433 | except Exception: | CODE |
| LOW | pydoll/browser/chromium/base.py | 890 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | docs/pt/deep-dive/fingerprinting/auditing.md | 0 | document.head.insertadjacenthtml('beforeend', '<style>.probe{--g: srgb} @media (color-gamut: p3){.probe{--g: p3}}</style | STRING |
| HIGH | docs/zh/deep-dive/fingerprinting/auditing.md | 0 | document.head.insertadjacenthtml('beforeend', '<style>.probe{--g: srgb} @media (color-gamut: p3){.probe{--g: p3}}</style | STRING |
| HIGH | docs/en/deep-dive/fingerprinting/auditing.md | 0 | document.head.insertadjacenthtml('beforeend', '<style>.probe{--g: srgb} @media (color-gamut: p3){.probe{--g: p3}}</style | STRING |
| HIGH | docs/pt/stealth/evasion-techniques.md | 0 | return { useragent: navigator.useragent, webdriver: navigator.webdriver, languages: navigator.languages, plugins: naviga | STRING |
| HIGH | docs/zh/stealth/evasion-techniques.md | 0 | return { useragent: navigator.useragent, webdriver: navigator.webdriver, languages: navigator.languages, plugins: naviga | STRING |
| HIGH | docs/en/stealth/evasion-techniques.md | 0 | return { useragent: navigator.useragent, webdriver: navigator.webdriver, languages: navigator.languages, plugins: naviga | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pydoll/browser/tab.py | 1324 | CODE | |
| LOW | pydoll/browser/tab.py | 1346 | CODE | |
| LOW | pydoll/browser/tab.py | 1364 | CODE | |
| LOW | pydoll/browser/tab.py | 1884 | CODE | |
| LOW | pydoll/elements/web_element.py | 857 | CODE | |
| LOW | pydoll/elements/mixins/find_elements_mixin.py | 71 | CODE | |
| LOW | pydoll/elements/mixins/find_elements_mixin.py | 85 | CODE | |
| LOW | pydoll/elements/mixins/find_elements_mixin.py | 99 | CODE | |
| LOW | pydoll/elements/mixins/find_elements_mixin.py | 113 | CODE | |
| LOW | pydoll/elements/mixins/find_elements_mixin.py | 127 | CODE | |
| LOW | pydoll/elements/mixins/find_elements_mixin.py | 140 | CODE | |
| LOW | pydoll/commands/target_commands.py | 152 | CODE | |
| LOW | pydoll/commands/network_commands.py | 322 | CODE | |
| LOW | pydoll/commands/runtime_commands.py | 111 | CODE | |
| LOW | pydoll/commands/runtime_commands.py | 241 | CODE | |
| LOW | pydoll/commands/page_commands.py | 385 | CODE | |
| LOW | pydoll/commands/input_commands.py | 82 | CODE | |
| LOW | pydoll/commands/input_commands.py | 171 | CODE | |
| LOW | pydoll/commands/input_commands.py | 524 | CODE | |
| LOW | pydoll/commands/emulation_commands.py | 144 | CODE | |
| LOW | pydoll/commands/emulation_commands.py | 285 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/unit/test_utils.py | 216 | # Create a file that exists but is not executable | COMMENT |
| MEDIUM⚡ | tests/unit/test_utils.py | 289 | # Create a temporary executable file | COMMENT |
| MEDIUM | tests/unit/test_utils.py | 161 | # Create a temporary executable file | COMMENT |
| MEDIUM | tests/integration/test_iframe_integration.py | 553 | # Create a test page with multiple iframes | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/integration/test_tab_io_integration.py | 54 | CODE | |
| LOW | tests/integration/test_tab_io_integration.py | 63 | CODE | |
| LOW | tests/integration/test_har_recording_integration.py | 61 | CODE | |
| LOW | tests/integration/test_tab_request_integration.py | 49 | CODE | |
| LOW | pydoll/connection/managers/events_manager.py | 171 | CODE | |
| LOW | pydoll/browser/fingerprint_applier.py | 357 | CODE | |
| LOW | pydoll/browser/fingerprint_applier.py | 390 | CODE | |
| LOW | pydoll/browser/tab.py | 1172 | CODE | |
| LOW | pydoll/browser/managers/temp_dir_manager.py | 127 | CODE | |
| LOW | pydoll/browser/requests/request.py | 508 | CODE | |
| LOW | pydoll/browser/requests/har_recorder.py | 585 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | README_zh.md | 235 | await (await tab.find(id='username')).type_text('user@example.com') | CODE |
| LOW | tests/integration/test_iframe_integration.py | 470 | placeholder = input_elem.get_attribute('placeholder') | CODE |
| LOW⚡ | tests/integration/test_extractor_integration.py | 265 | assert article.author.name == 'Jane Doe' | CODE |
| LOW | tests/integration/test_extractor_integration.py | 331 | assert data['author']['name'] == 'Jane Doe' | CODE |
| LOW | tests/integration/test_extractor_integration.py | 553 | assert article.author_name == 'Jane Doe' | CODE |
| LOW | tests/integration/test_core_integration.py | 182 | test_text = 'user@example.com' | CODE |
| LOW | tests/integration/pages/web_element.html | 78 | <input id="email-input" type="email" value="user@example.com"> | CODE |
| LOW | pydoll/protocol/dom/types.py | 47 | PLACEHOLDER = 'placeholder' | CODE |
| LOW | pydoll/protocol/accessibility/types.py | 38 | PLACEHOLDER = 'placeholder' | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pydoll/interactions/scroll.py | 154 | # Check if we are stuck | COMMENT |
| LOW | pydoll/utils/general.py | 250 | # Check if return is inside a function by counting braces | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | .github/ISSUE_TEMPLATE/feature_request.yml | 29 | placeholder: I'm trying to accomplish X, but I'm unable to because Y... | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pydoll/utils/fingerprint_builder.py | 61 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | pydoll/elements/web_element.py | 837 | """Check if element is visible using comprehensive JavaScript visibility test.""" | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pydoll/decorators.py | 96 | def my_function(): | STRING |