import pyautogui
import random
import time
import math
import numpy as np
"""
This script demonstrates techniques to make pyautogui automation more human-like
to potentially reduce detection by Cloudflare and similar bot detection systems.
"""
# Disable pyautogui's built-in safety feature for this example
pyautogui.FAILSAFE = True
# Get screen size for reference
screen_width, screen_height = pyautogui.size()
def human_like_mouse_movement(start_x, start_y, end_x, end_y, duration=None):
"""
Move the mouse in a human-like manner between two points.
Uses Bezier curves to create natural movement arcs.
"""
# Calculate distance between points
distance = math.sqrt((end_x - start_x) ** 2 + (end_y - start_y) ** 2)
# Set a reasonable duration based on distance if not specified
if duration is None:
# Longer distance = longer time, but not linear
duration = 0.6 + (distance / 500) * random.uniform(0.5, 1.5)
# Add slight randomness to end coordinates (humans aren't pixel-perfect)
end_x += random.randint(-2, 2)
end_y += random.randint(-2, 2)
# Create a Bezier curve for more natural movement
# More control points = more complex and potentially more natural curve
control_points = []
# Start point
control_points.append((start_x, start_y))
# Add 1-3 control points for complexity
num_control_points = random.randint(1, 3)
for i in range(num_control_points):
# Create control points that deviate from the straight line
# The longer the distance, the more deviation we allow
deviation = distance * 0.1 * random.uniform(0.5, 1.5)
# Calculate a point along the direct path
ratio = (i + 1) / (num_control_points + 1)
point_x = start_x + (end_x - start_x) * ratio
point_y = start_y + (end_y - start_y) * ratio
# Add some randomized deviation
point_x += random.uniform(-deviation, deviation)
point_y += random.uniform(-deviation, deviation)
control_points.append((point_x, point_y))
# End point
control_points.append((end_x, end_y))
# Generate points along the Bezier curve
steps = int(duration * 60) # 60 points per second for smooth movement
points = bezier_curve(control_points, steps)
# Move the mouse along the curve with variable speed
last_time = time.time()
for i, (x, y) in enumerate(points):
# Calculate progress ratio (0 to 1)
progress = i / (steps - 1)
# Apply easing function for natural acceleration/deceleration
# Ease in at the beginning, ease out at the end
if progress < 0.2:
# Ease in - gradually accelerate
speed_factor = progress / 0.2
elif progress > 0.8:
# Ease out - gradually decelerate
speed_factor = (1 - progress) / 0.2
else:
# Maintain relatively consistent speed in the middle
speed_factor = 1.0
# Add slight random variations to speed
speed_factor *= random.uniform(0.9, 1.1)
print(f'duration: {duration} steps: {steps} speed_factor: {speed_factor}')
if speed_factor == 0.0:
continue
# Calculate the ideal time we should be at this point
ideal_time = last_time + (duration / steps) / speed_factor
# Wait until we reach the ideal time
current_time = time.time()
if current_time < ideal_time:
time.sleep(ideal_time - current_time)
# Move to the point
pyautogui.moveTo(int(x), int(y))
last_time = time.time()
def bezier_curve(control_points, steps):
"""
Generate a Bezier curve based on control points.
Returns a list of points along the curve.
"""
n = len(control_points) - 1
points = []
for t in np.linspace(0, 1, steps):
point = [0, 0]
for i in range(n + 1):
binomial = math.comb(n, i)
point[0] += binomial * (1 - t) ** (n - i) * t ** i * control_points[i][0]
point[1] += binomial * (1 - t) ** (n - i) * t ** i * control_points[i][1]
points.append(point)
return points
def human_like_click(x=None, y=None, button='left'):
"""
Perform a human-like click operation.
If x and y are not provided, clicks at current position.
"""
# If coordinates are provided, move to that position first
if x is not None and y is not None:
current_x, current_y = pyautogui.position()
human_like_mouse_movement(current_x, current_y, x, y)
# Add a small delay before clicking (humans pause before clicking)
time.sleep(random.uniform(0.05, 0.15))
# Click with variable duration
click_duration = random.uniform(0.05, 0.15)
pyautogui.mouseDown(button=button)
time.sleep(click_duration)
pyautogui.mouseUp(button=button)
# Add a small delay after clicking (humans pause after clicking)
time.sleep(random.uniform(0.05, 0.1))
def human_like_scroll(clicks, direction='down'):
"""
Scroll in a human-like manner.
"""
# Humans don't scroll at a constant speed
for _ in range(clicks):
# Variable scroll amount
scroll_amount = random.randint(1, 5)
if direction == 'down':
pyautogui.scroll(-scroll_amount)
else:
pyautogui.scroll(scroll_amount)
# Random pause between scrolls
time.sleep(random.uniform(0.05, 0.3))
def human_like_type(text, interval=None):
"""
Type text with variable speed like a human.
"""
for char in text:
# Humans type at variable speeds
if interval is None:
# Different characters take different times to type
if char in '.,?!':
# Longer pauses for punctuation
typing_speed = random.uniform(0.1, 0.3)
elif char == ' ':
# Spaces are typically faster
typing_speed = random.uniform(0.05, 0.15)
else:
# Normal characters
typing_speed = random.uniform(0.05, 0.2)
else:
# Use provided interval with some randomness
typing_speed = interval * random.uniform(0.8, 1.2)
pyautogui.typewrite(char)
time.sleep(typing_speed)
# Occasionally add a longer pause (as if thinking)
if random.random() < 0.02:
time.sleep(random.uniform(0.5, 1.0))
def add_natural_pauses():
"""
Add a natural pause as if the user is reading or thinking.
Call this function between logical actions.
"""
# Determine pause type (short, medium, long)
pause_type = random.choices(
['short', 'medium', 'long', 'very_long'],
weights=[0.6, 0.3, 0.08, 0.02],
k=1
)[0]
if pause_type == 'short':
time.sleep(random.uniform(0.5, 1.5))
elif pause_type == 'medium':
time.sleep(random.uniform(1.5, 3.0))
elif pause_type == 'long':
time.sleep(random.uniform(3.0, 6.0))
else: # very_long
time.sleep(random.uniform(6.0, 10.0))
def random_mouse_movement():
"""
Occasionally move the mouse randomly as humans do when thinking or reading.
"""
current_x, current_y = pyautogui.position()
# Small random movement around current position
offset_x = random.randint(-100, 100)
offset_y = random.randint(-100, 100)
# Ensure we stay within screen bounds
target_x = max(0, min(screen_width - 1, current_x + offset_x))
target_y = max(0, min(screen_height - 1, current_y + offset_y))
# Move to the random position
human_like_mouse_movement(current_x, current_y, target_x, target_y)
# Example usage
if __name__ == "__main__":
# Give user time to switch to the target window
print("Switch to your target window. Starting in 3 seconds...")
time.sleep(3)
# Example: Navigate to a website and interact with it
def example_automation():
# Simulate opening a new tab (Ctrl+T)
pyautogui.hotkey('ctrl', 't')
add_natural_pauses()
# Type a URL
# human_like_type("https://visa.vfsglobal.com/chn/zh/can/login")
# add_natural_pauses()
# Press Enter
# pyautogui.press('enter')
# Wait for page to load with natural variation
time.sleep(random.uniform(2.0, 3.5))
# Scroll down a bit
human_like_scroll(random.randint(3, 7))
add_natural_pauses()
# Move to a random position as if reading
# random_mouse_movement()
# add_natural_pauses()
# Scroll more
# human_like_scroll(random.randint(2, 5))
# add_natural_pauses()
# Click somewhere (simulating clicking a link)
current_x, current_y = pyautogui.position()
# 695 508
print(current_x, current_y)
target_x = current_x + random.randint(-100, 100)
target_y = current_y + random.randint(-50, 50)
# 模拟点击cloud flare
human_like_click(695, 508)
# Uncomment to run the example
example_automation()
print("Example complete. You can modify this script for your specific needs.")
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)