Steel Python SDK: Browser Automation That Actually Works
Steel Python SDK: Browser Automation That Actually Works
Jul 20, 2025
Jul 20, 2025
/
San Francisco
/

Nikola Balic
Nikola Balic

You know the drill. You need to scrape some data, automate a workflow, or test that cursed SPA that breaks every other week. You fire up Playwright, spend 2 hours configuring Docker, another hour debugging why your bot got blocked, and then realize you need to handle CAPTCHAs. What if we just... didn't? Steel's Python SDK is browser automation for people who want to ship, not spend their weekend becoming a DevOps expert.
Installation (The Easy Part)
That's it. No Docker, no browser downloads, no "works on my machine" negative energy.
Your First Steel Session
Here's how you create a cloud browser session in just a few lines:
from steel import Steel import os # Initialize the client api_key = os.getenv("STEEL_API_KEY") client = Steel(steel_api_key=api_key) try: # Create a browser session with anti-bot protection session = client.sessions.create() print(f"Session ID: {session.id}") print(f"Watch live at: {session.session_viewer_url}") except Exception as e: print(f"Error creating session: {e}")
from steel import Steel import os # Initialize the client api_key = os.getenv("STEEL_API_KEY") client = Steel(steel_api_key=api_key) try: # Create a browser session with anti-bot protection session = client.sessions.create() print(f"Session ID: {session.id}") print(f"Watch live at: {session.session_viewer_url}") except Exception as e: print(f"Error creating session: {e}")
from steel import Steel import os # Initialize the client api_key = os.getenv("STEEL_API_KEY") client = Steel(steel_api_key=api_key) try: # Create a browser session with anti-bot protection session = client.sessions.create() print(f"Session ID: {session.id}") print(f"Watch live at: {session.session_viewer_url}") except Exception as e: print(f"Error creating session: {e}")
from steel import Steel import os # Initialize the client api_key = os.getenv("STEEL_API_KEY") client = Steel(steel_api_key=api_key) try: # Create a browser session with anti-bot protection session = client.sessions.create() print(f"Session ID: {session.id}") print(f"Watch live at: {session.session_viewer_url}") except Exception as e: print(f"Error creating session: {e}")
No cap - that's a full browser running in the cloud with anti-bot protection enabled. You can literally watch it live in your browser.
Connect Your Favorite Tools
Steel provides WebSocket URLs that work with browser automation tools. Here's how to get the connection details:
import asyncio import os from steel import Steel async def get_browser_connection(): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create a browser session session = client.sessions.create() print(f"Session ID: {session.id}") print(f"WebSocket URL: {session.websocket_url}") # Note: To connect Puppeteer (Node.js), use: print(f"\nFor Puppeteer connection:") print(f"browserWSEndpoint: '{session.websocket_url}'") # Clean up client.sessions.release(session.id) except Exception as e: print(f"Error: {e}") # Run the async function asyncio.run(get_browser_connection())
import asyncio import os from steel import Steel async def get_browser_connection(): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create a browser session session = client.sessions.create() print(f"Session ID: {session.id}") print(f"WebSocket URL: {session.websocket_url}") # Note: To connect Puppeteer (Node.js), use: print(f"\nFor Puppeteer connection:") print(f"browserWSEndpoint: '{session.websocket_url}'") # Clean up client.sessions.release(session.id) except Exception as e: print(f"Error: {e}") # Run the async function asyncio.run(get_browser_connection())
import asyncio import os from steel import Steel async def get_browser_connection(): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create a browser session session = client.sessions.create() print(f"Session ID: {session.id}") print(f"WebSocket URL: {session.websocket_url}") # Note: To connect Puppeteer (Node.js), use: print(f"\nFor Puppeteer connection:") print(f"browserWSEndpoint: '{session.websocket_url}'") # Clean up client.sessions.release(session.id) except Exception as e: print(f"Error: {e}") # Run the async function asyncio.run(get_browser_connection())
import asyncio import os from steel import Steel async def get_browser_connection(): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create a browser session session = client.sessions.create() print(f"Session ID: {session.id}") print(f"WebSocket URL: {session.websocket_url}") # Note: To connect Puppeteer (Node.js), use: print(f"\nFor Puppeteer connection:") print(f"browserWSEndpoint: '{session.websocket_url}'") # Clean up client.sessions.release(session.id) except Exception as e: print(f"Error: {e}") # Run the async function asyncio.run(get_browser_connection())
Same API you know, but now it's running on infrastructure that doesn't hate you.
Real-World Examples That Actually Work
Price Monitoring (Because Everything's Expensive)
import asyncio import os from steel import Steel async def check_price(product_url): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create session with all the good stuff enabled # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True # Requires paid plan ) print(f"Session created: {session.id}") print(f"WebSocket URL for browser connection: {session.websocket_url}") # Note: To implement full price monitoring, you would: # 1. Connect your browser automation tool to session.websocket_url # 2. Navigate to product_url # 3. Wait for price element # 4. Extract price data price_data = { "session_id": session.id, "product_url": product_url, "websocket_url": session.websocket_url, "status": "session_ready_for_browser_connection" } # Clean up client.sessions.release(session.id) return price_data except Exception as e: print(f"Error in price monitoring: {e}") return None # Example usage async def main(): result = await check_price("https://example.com/product") print("Price monitoring result:", result) asyncio.run(main())
import asyncio import os from steel import Steel async def check_price(product_url): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create session with all the good stuff enabled # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True # Requires paid plan ) print(f"Session created: {session.id}") print(f"WebSocket URL for browser connection: {session.websocket_url}") # Note: To implement full price monitoring, you would: # 1. Connect your browser automation tool to session.websocket_url # 2. Navigate to product_url # 3. Wait for price element # 4. Extract price data price_data = { "session_id": session.id, "product_url": product_url, "websocket_url": session.websocket_url, "status": "session_ready_for_browser_connection" } # Clean up client.sessions.release(session.id) return price_data except Exception as e: print(f"Error in price monitoring: {e}") return None # Example usage async def main(): result = await check_price("https://example.com/product") print("Price monitoring result:", result) asyncio.run(main())
import asyncio import os from steel import Steel async def check_price(product_url): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create session with all the good stuff enabled # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True # Requires paid plan ) print(f"Session created: {session.id}") print(f"WebSocket URL for browser connection: {session.websocket_url}") # Note: To implement full price monitoring, you would: # 1. Connect your browser automation tool to session.websocket_url # 2. Navigate to product_url # 3. Wait for price element # 4. Extract price data price_data = { "session_id": session.id, "product_url": product_url, "websocket_url": session.websocket_url, "status": "session_ready_for_browser_connection" } # Clean up client.sessions.release(session.id) return price_data except Exception as e: print(f"Error in price monitoring: {e}") return None # Example usage async def main(): result = await check_price("https://example.com/product") print("Price monitoring result:", result) asyncio.run(main())
import asyncio import os from steel import Steel async def check_price(product_url): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Create session with all the good stuff enabled # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True # Requires paid plan ) print(f"Session created: {session.id}") print(f"WebSocket URL for browser connection: {session.websocket_url}") # Note: To implement full price monitoring, you would: # 1. Connect your browser automation tool to session.websocket_url # 2. Navigate to product_url # 3. Wait for price element # 4. Extract price data price_data = { "session_id": session.id, "product_url": product_url, "websocket_url": session.websocket_url, "status": "session_ready_for_browser_connection" } # Clean up client.sessions.release(session.id) return price_data except Exception as e: print(f"Error in price monitoring: {e}") return None # Example usage async def main(): result = await check_price("https://example.com/product") print("Price monitoring result:", result) asyncio.run(main())
Form Automation (For When You're Too Lazy to Click)
import asyncio import os from steel import Steel async def fill_application_form(form_url, user_data): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Extended timeout because forms are complicated # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True, # Requires paid plan timeout=3600000 # 1 hour, because government websites ) print(f"Session created: {session.id}") print(f"WebSocket URL: {session.websocket_url}") print(f"Form URL to automate: {form_url}") print(f"User data: {user_data}") # Note: With a browser automation library connected, you would: # 1. Connect to session.websocket_url # 2. Navigate to form_url # 3. Fill form fields with user_data # 4. Submit form and handle navigation form_automation_plan = { "session_id": session.id, "websocket_url": session.websocket_url, "form_url": form_url, "automation_steps": [ f"Fill firstName with: {user_data.get('first_name', 'N/A')}", f"Fill lastName with: {user_data.get('last_name', 'N/A')}", f"Fill email with: {user_data.get('email', 'N/A')}", f"Select country: {user_data.get('country', 'N/A')}", "Submit form and wait for step-2" ] } # Clean up client.sessions.release(session.id) return form_automation_plan except Exception as e: print(f"Error in form automation: {e}") return None # Example usage async def main(): sample_user_data = { 'first_name': 'John', 'last_name': 'Doe', 'email': 'john.doe@example.com', 'country': 'US' } result = await fill_application_form("https://example.com/application-form", sample_user_data) print("Form automation result:", result) asyncio.run(main())
import asyncio import os from steel import Steel async def fill_application_form(form_url, user_data): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Extended timeout because forms are complicated # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True, # Requires paid plan timeout=3600000 # 1 hour, because government websites ) print(f"Session created: {session.id}") print(f"WebSocket URL: {session.websocket_url}") print(f"Form URL to automate: {form_url}") print(f"User data: {user_data}") # Note: With a browser automation library connected, you would: # 1. Connect to session.websocket_url # 2. Navigate to form_url # 3. Fill form fields with user_data # 4. Submit form and handle navigation form_automation_plan = { "session_id": session.id, "websocket_url": session.websocket_url, "form_url": form_url, "automation_steps": [ f"Fill firstName with: {user_data.get('first_name', 'N/A')}", f"Fill lastName with: {user_data.get('last_name', 'N/A')}", f"Fill email with: {user_data.get('email', 'N/A')}", f"Select country: {user_data.get('country', 'N/A')}", "Submit form and wait for step-2" ] } # Clean up client.sessions.release(session.id) return form_automation_plan except Exception as e: print(f"Error in form automation: {e}") return None # Example usage async def main(): sample_user_data = { 'first_name': 'John', 'last_name': 'Doe', 'email': 'john.doe@example.com', 'country': 'US' } result = await fill_application_form("https://example.com/application-form", sample_user_data) print("Form automation result:", result) asyncio.run(main())
import asyncio import os from steel import Steel async def fill_application_form(form_url, user_data): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Extended timeout because forms are complicated # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True, # Requires paid plan timeout=3600000 # 1 hour, because government websites ) print(f"Session created: {session.id}") print(f"WebSocket URL: {session.websocket_url}") print(f"Form URL to automate: {form_url}") print(f"User data: {user_data}") # Note: With a browser automation library connected, you would: # 1. Connect to session.websocket_url # 2. Navigate to form_url # 3. Fill form fields with user_data # 4. Submit form and handle navigation form_automation_plan = { "session_id": session.id, "websocket_url": session.websocket_url, "form_url": form_url, "automation_steps": [ f"Fill firstName with: {user_data.get('first_name', 'N/A')}", f"Fill lastName with: {user_data.get('last_name', 'N/A')}", f"Fill email with: {user_data.get('email', 'N/A')}", f"Select country: {user_data.get('country', 'N/A')}", "Submit form and wait for step-2" ] } # Clean up client.sessions.release(session.id) return form_automation_plan except Exception as e: print(f"Error in form automation: {e}") return None # Example usage async def main(): sample_user_data = { 'first_name': 'John', 'last_name': 'Doe', 'email': 'john.doe@example.com', 'country': 'US' } result = await fill_application_form("https://example.com/application-form", sample_user_data) print("Form automation result:", result) asyncio.run(main())
import asyncio import os from steel import Steel async def fill_application_form(form_url, user_data): api_key = os.getenv("STEEL_API_KEY") try: # Initialize Steel client client = Steel(steel_api_key=api_key) # Extended timeout because forms are complicated # Note: use_proxy and solve_captcha require paid plan session = client.sessions.create( # use_proxy=True, # Requires paid plan # solve_captcha=True, # Requires paid plan timeout=3600000 # 1 hour, because government websites ) print(f"Session created: {session.id}") print(f"WebSocket URL: {session.websocket_url}") print(f"Form URL to automate: {form_url}") print(f"User data: {user_data}") # Note: With a browser automation library connected, you would: # 1. Connect to session.websocket_url # 2. Navigate to form_url # 3. Fill form fields with user_data # 4. Submit form and handle navigation form_automation_plan = { "session_id": session.id, "websocket_url": session.websocket_url, "form_url": form_url, "automation_steps": [ f"Fill firstName with: {user_data.get('first_name', 'N/A')}", f"Fill lastName with: {user_data.get('last_name', 'N/A')}", f"Fill email with: {user_data.get('email', 'N/A')}", f"Select country: {user_data.get('country', 'N/A')}", "Submit form and wait for step-2" ] } # Clean up client.sessions.release(session.id) return form_automation_plan except Exception as e: print(f"Error in form automation: {e}") return None # Example usage async def main(): sample_user_data = { 'first_name': 'John', 'last_name': 'Doe', 'email': 'john.doe@example.com', 'country': 'US' } result = await fill_application_form("https://example.com/application-form", sample_user_data) print("Form automation result:", result) asyncio.run(main())
The Secret Sauce: Built-in Anti-Bot Protection
Here's what you get with paid plans:
Residential proxy rotation - No more IP bans
Automatic CAPTCHA solving - For common types (sorry, no magic)
Browser fingerprint randomization - Look like a different human every time
Human-like behavior simulation - Mouse movements that don't scream "I'M A BOT"
All enabled with one flag: use_proxy=True, solve_captcha=True
Note: These features require upgrading from the hobby (free) plan. The hobby plan still gives you cloud browsers with basic anti-detection.
Session Management That Makes Sense
Sessions stick around for up to 24 hours and maintain state across requests:
try: # Create a session session = client.sessions.create( timeout=86400000 # 24 hours in milliseconds ) print(f"Session created: {session.id}") print(f"Session URL: {session.session_viewer_url}") # Do some work # ... browser automation happens here ... print("Browser automation would happen here...") # Come back later and the session is still there session_details = client.sessions.retrieve(session.id) print(f"Status: {session_details.status}") # Clean up when done client.sessions.release(session.id) print("Session released successfully") except Exception as e: print(f"Error in session management: {e}")
try: # Create a session session = client.sessions.create( timeout=86400000 # 24 hours in milliseconds ) print(f"Session created: {session.id}") print(f"Session URL: {session.session_viewer_url}") # Do some work # ... browser automation happens here ... print("Browser automation would happen here...") # Come back later and the session is still there session_details = client.sessions.retrieve(session.id) print(f"Status: {session_details.status}") # Clean up when done client.sessions.release(session.id) print("Session released successfully") except Exception as e: print(f"Error in session management: {e}")
try: # Create a session session = client.sessions.create( timeout=86400000 # 24 hours in milliseconds ) print(f"Session created: {session.id}") print(f"Session URL: {session.session_viewer_url}") # Do some work # ... browser automation happens here ... print("Browser automation would happen here...") # Come back later and the session is still there session_details = client.sessions.retrieve(session.id) print(f"Status: {session_details.status}") # Clean up when done client.sessions.release(session.id) print("Session released successfully") except Exception as e: print(f"Error in session management: {e}")
try: # Create a session session = client.sessions.create( timeout=86400000 # 24 hours in milliseconds ) print(f"Session created: {session.id}") print(f"Session URL: {session.session_viewer_url}") # Do some work # ... browser automation happens here ... print("Browser automation would happen here...") # Come back later and the session is still there session_details = client.sessions.retrieve(session.id) print(f"Status: {session_details.status}") # Clean up when done client.sessions.release(session.id) print("Session released successfully") except Exception as e: print(f"Error in session management: {e}")
Pro tip: Use the session viewer URL to watch your automation live. It's surprisingly satisfying.
Error Handling (Because Things Break)
import asyncio import time import random import os from steel import Steel async def scrape_the_thing(session, url): """Placeholder function for actual scraping logic.""" print(f"Scraping {url} using session {session.id}") # Simulate some work and potential failure if random.random() < 0.3: # 30% chance of failure for testing raise Exception("Simulated scraping failure") return {"url": url, "data": "scraped_data", "session_id": session.id} async def robust_automation(url, max_retries=3): api_key = os.getenv("STEEL_API_KEY") if not api_key: raise Exception("STEEL_API_KEY environment variable is not set") client = Steel(steel_api_key=api_key) for attempt in range(max_retries): session = None try: # Create session session = client.sessions.create() print(f"Attempt {attempt + 1}: Created session {session.id}") # Your automation logic here result = await scrape_the_thing(session, url) # Clean up client.sessions.release(session.id) print(f"Success on attempt {attempt + 1}") return result except Exception as error: print(f"Attempt {attempt + 1} failed: {error}") # Clean up session if it was created if session: try: client.sessions.release(session.id) except: pass # Ignore cleanup errors if attempt < max_retries - 1: # Exponential backoff with jitter (because we're not animals) delay = (2 ** attempt) + random.uniform(0, 1) print(f"Waiting {delay:.2f} seconds before retry...") await asyncio.sleep(delay) # Use asyncio.sleep in async functions raise Exception(f"Failed after {max_retries} attempts") # Example usage async def main(): try: result = await robust_automation("https://example.com", max_retries=3) print("Final result:", result) except Exception as e: print(f"Robust automation failed: {e}") asyncio.run(main())
import asyncio import time import random import os from steel import Steel async def scrape_the_thing(session, url): """Placeholder function for actual scraping logic.""" print(f"Scraping {url} using session {session.id}") # Simulate some work and potential failure if random.random() < 0.3: # 30% chance of failure for testing raise Exception("Simulated scraping failure") return {"url": url, "data": "scraped_data", "session_id": session.id} async def robust_automation(url, max_retries=3): api_key = os.getenv("STEEL_API_KEY") if not api_key: raise Exception("STEEL_API_KEY environment variable is not set") client = Steel(steel_api_key=api_key) for attempt in range(max_retries): session = None try: # Create session session = client.sessions.create() print(f"Attempt {attempt + 1}: Created session {session.id}") # Your automation logic here result = await scrape_the_thing(session, url) # Clean up client.sessions.release(session.id) print(f"Success on attempt {attempt + 1}") return result except Exception as error: print(f"Attempt {attempt + 1} failed: {error}") # Clean up session if it was created if session: try: client.sessions.release(session.id) except: pass # Ignore cleanup errors if attempt < max_retries - 1: # Exponential backoff with jitter (because we're not animals) delay = (2 ** attempt) + random.uniform(0, 1) print(f"Waiting {delay:.2f} seconds before retry...") await asyncio.sleep(delay) # Use asyncio.sleep in async functions raise Exception(f"Failed after {max_retries} attempts") # Example usage async def main(): try: result = await robust_automation("https://example.com", max_retries=3) print("Final result:", result) except Exception as e: print(f"Robust automation failed: {e}") asyncio.run(main())
import asyncio import time import random import os from steel import Steel async def scrape_the_thing(session, url): """Placeholder function for actual scraping logic.""" print(f"Scraping {url} using session {session.id}") # Simulate some work and potential failure if random.random() < 0.3: # 30% chance of failure for testing raise Exception("Simulated scraping failure") return {"url": url, "data": "scraped_data", "session_id": session.id} async def robust_automation(url, max_retries=3): api_key = os.getenv("STEEL_API_KEY") if not api_key: raise Exception("STEEL_API_KEY environment variable is not set") client = Steel(steel_api_key=api_key) for attempt in range(max_retries): session = None try: # Create session session = client.sessions.create() print(f"Attempt {attempt + 1}: Created session {session.id}") # Your automation logic here result = await scrape_the_thing(session, url) # Clean up client.sessions.release(session.id) print(f"Success on attempt {attempt + 1}") return result except Exception as error: print(f"Attempt {attempt + 1} failed: {error}") # Clean up session if it was created if session: try: client.sessions.release(session.id) except: pass # Ignore cleanup errors if attempt < max_retries - 1: # Exponential backoff with jitter (because we're not animals) delay = (2 ** attempt) + random.uniform(0, 1) print(f"Waiting {delay:.2f} seconds before retry...") await asyncio.sleep(delay) # Use asyncio.sleep in async functions raise Exception(f"Failed after {max_retries} attempts") # Example usage async def main(): try: result = await robust_automation("https://example.com", max_retries=3) print("Final result:", result) except Exception as e: print(f"Robust automation failed: {e}") asyncio.run(main())
import asyncio import time import random import os from steel import Steel async def scrape_the_thing(session, url): """Placeholder function for actual scraping logic.""" print(f"Scraping {url} using session {session.id}") # Simulate some work and potential failure if random.random() < 0.3: # 30% chance of failure for testing raise Exception("Simulated scraping failure") return {"url": url, "data": "scraped_data", "session_id": session.id} async def robust_automation(url, max_retries=3): api_key = os.getenv("STEEL_API_KEY") if not api_key: raise Exception("STEEL_API_KEY environment variable is not set") client = Steel(steel_api_key=api_key) for attempt in range(max_retries): session = None try: # Create session session = client.sessions.create() print(f"Attempt {attempt + 1}: Created session {session.id}") # Your automation logic here result = await scrape_the_thing(session, url) # Clean up client.sessions.release(session.id) print(f"Success on attempt {attempt + 1}") return result except Exception as error: print(f"Attempt {attempt + 1} failed: {error}") # Clean up session if it was created if session: try: client.sessions.release(session.id) except: pass # Ignore cleanup errors if attempt < max_retries - 1: # Exponential backoff with jitter (because we're not animals) delay = (2 ** attempt) + random.uniform(0, 1) print(f"Waiting {delay:.2f} seconds before retry...") await asyncio.sleep(delay) # Use asyncio.sleep in async functions raise Exception(f"Failed after {max_retries} attempts") # Example usage async def main(): try: result = await robust_automation("https://example.com", max_retries=3) print("Final result:", result) except Exception as e: print(f"Robust automation failed: {e}") asyncio.run(main())
File Management (Upload/Download Vibes)
Need to handle files? We got you:
# Upload a file to your session file_upload = client.sessions.files.upload( session_id=session.id, file=open('document.pdf', 'rb'), path='uploads/document.pdf' ) # Download files from your session file_data = client.sessions.files.download( session_id=session.id, path='downloads/result.pdf' ) # Download everything as a zip archive = client.sessions.files.download_archive(session_id=session.id)
# Upload a file to your session file_upload = client.sessions.files.upload( session_id=session.id, file=open('document.pdf', 'rb'), path='uploads/document.pdf' ) # Download files from your session file_data = client.sessions.files.download( session_id=session.id, path='downloads/result.pdf' ) # Download everything as a zip archive = client.sessions.files.download_archive(session_id=session.id)
# Upload a file to your session file_upload = client.sessions.files.upload( session_id=session.id, file=open('document.pdf', 'rb'), path='uploads/document.pdf' ) # Download files from your session file_data = client.sessions.files.download( session_id=session.id, path='downloads/result.pdf' ) # Download everything as a zip archive = client.sessions.files.download_archive(session_id=session.id)
# Upload a file to your session file_upload = client.sessions.files.upload( session_id=session.id, file=open('document.pdf', 'rb'), path='uploads/document.pdf' ) # Download files from your session file_data = client.sessions.files.download( session_id=session.id, path='downloads/result.pdf' ) # Download everything as a zip archive = client.sessions.files.download_archive(session_id=session.id)
Quick Start for the Impatient
from steel import Steel import os # Set your API key (get one at steel.dev) client = Steel(steel_api_key=os.getenv("STEEL_API_KEY")) # Create session with the works session = client.sessions.create( use_proxy=True, solve_captcha=True, block_ads=True # Because ads are annoying ) print(f"โจ Session created: {session.id}") print(f"๐ Watch live: {session.session_viewer_url}") print(f"๐ WebSocket: {session.websocket_url}") # Connect your favorite automation tool and go wild
from steel import Steel import os # Set your API key (get one at steel.dev) client = Steel(steel_api_key=os.getenv("STEEL_API_KEY")) # Create session with the works session = client.sessions.create( use_proxy=True, solve_captcha=True, block_ads=True # Because ads are annoying ) print(f"โจ Session created: {session.id}") print(f"๐ Watch live: {session.session_viewer_url}") print(f"๐ WebSocket: {session.websocket_url}") # Connect your favorite automation tool and go wild
from steel import Steel import os # Set your API key (get one at steel.dev) client = Steel(steel_api_key=os.getenv("STEEL_API_KEY")) # Create session with the works session = client.sessions.create( use_proxy=True, solve_captcha=True, block_ads=True # Because ads are annoying ) print(f"โจ Session created: {session.id}") print(f"๐ Watch live: {session.session_viewer_url}") print(f"๐ WebSocket: {session.websocket_url}") # Connect your favorite automation tool and go wild
from steel import Steel import os # Set your API key (get one at steel.dev) client = Steel(steel_api_key=os.getenv("STEEL_API_KEY")) # Create session with the works session = client.sessions.create( use_proxy=True, solve_captcha=True, block_ads=True # Because ads are annoying ) print(f"โจ Session created: {session.id}") print(f"๐ Watch live: {session.session_viewer_url}") print(f"๐ WebSocket: {session.websocket_url}") # Connect your favorite automation tool and go wild
Next Steps (Ship Something Cool)
Ready to build? Check out:
Python SDK on GitHub - All the code and examples
Steel Cookbook - Real examples that work
Discord Community - Get help, share wins
Free tier gives you 100 browser hours per month - perfect for testing and small projects.
The Bottom Line
Steel's Python SDK removes the infrastructure headaches so you can focus on building cool stuff. No Docker containers to manage, no proxy services to configure, no CAPTCHAs to solve manually.
Just pip install steel-sdk and start automating.
Questions? Hit us up in Discord or check the docs. We're here to help you ship faster.
Ready to try it? Get your free API key and let's see what you build. ๐
All Systems Operational

