Spaces:
Sleeping
Sleeping
| ### Using `storage_state` to Pre-Load Cookies and LocalStorage | |
| Crawl4ai’s `AsyncWebCrawler` lets you preserve and reuse session data, including cookies and localStorage, across multiple runs. By providing a `storage_state`, you can start your crawls already “logged in” or with any other necessary session data—no need to repeat the login flow every time. | |
| #### What is `storage_state`? | |
| `storage_state` can be: | |
| - A dictionary containing cookies and localStorage data. | |
| - A path to a JSON file that holds this information. | |
| When you pass `storage_state` to the crawler, it applies these cookies and localStorage entries before loading any pages. This means your crawler effectively starts in a known authenticated or pre-configured state. | |
| #### Example Structure | |
| Here’s an example storage state: | |
| ```json | |
| { | |
| "cookies": [ | |
| { | |
| "name": "session", | |
| "value": "abcd1234", | |
| "domain": "example.com", | |
| "path": "/", | |
| "expires": 1675363572.037711, | |
| "httpOnly": false, | |
| "secure": false, | |
| "sameSite": "None" | |
| } | |
| ], | |
| "origins": [ | |
| { | |
| "origin": "https://example.com", | |
| "localStorage": [ | |
| { "name": "token", "value": "my_auth_token" }, | |
| { "name": "refreshToken", "value": "my_refresh_token" } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| This JSON sets a `session` cookie and two localStorage entries (`token` and `refreshToken`) for `https://example.com`. | |
| --- | |
| ### Passing `storage_state` as a Dictionary | |
| You can directly provide the data as a dictionary: | |
| ```python | |
| import asyncio | |
| from crawl4ai import AsyncWebCrawler | |
| async def main(): | |
| storage_dict = { | |
| "cookies": [ | |
| { | |
| "name": "session", | |
| "value": "abcd1234", | |
| "domain": "example.com", | |
| "path": "/", | |
| "expires": 1675363572.037711, | |
| "httpOnly": False, | |
| "secure": False, | |
| "sameSite": "None" | |
| } | |
| ], | |
| "origins": [ | |
| { | |
| "origin": "https://example.com", | |
| "localStorage": [ | |
| {"name": "token", "value": "my_auth_token"}, | |
| {"name": "refreshToken", "value": "my_refresh_token"} | |
| ] | |
| } | |
| ] | |
| } | |
| async with AsyncWebCrawler( | |
| headless=True, | |
| storage_state=storage_dict | |
| ) as crawler: | |
| result = await crawler.arun(url='https://example.com/protected') | |
| if result.success: | |
| print("Crawl succeeded with pre-loaded session data!") | |
| print("Page HTML length:", len(result.html)) | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |
| ``` | |
| --- | |
| ### Passing `storage_state` as a File | |
| If you prefer a file-based approach, save the JSON above to `mystate.json` and reference it: | |
| ```python | |
| import asyncio | |
| from crawl4ai import AsyncWebCrawler | |
| async def main(): | |
| async with AsyncWebCrawler( | |
| headless=True, | |
| storage_state="mystate.json" # Uses a JSON file instead of a dictionary | |
| ) as crawler: | |
| result = await crawler.arun(url='https://example.com/protected') | |
| if result.success: | |
| print("Crawl succeeded with pre-loaded session data!") | |
| print("Page HTML length:", len(result.html)) | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |
| ``` | |
| --- | |
| ### Using `storage_state` to Avoid Repeated Logins (Sign In Once, Use Later) | |
| A common scenario is when you need to log in to a site (entering username/password, etc.) to access protected pages. Doing so every crawl is cumbersome. Instead, you can: | |
| 1. Perform the login once in a hook. | |
| 2. After login completes, export the resulting `storage_state` to a file. | |
| 3. On subsequent runs, provide that `storage_state` to skip the login step. | |
| **Step-by-Step Example:** | |
| **First Run (Perform Login and Save State):** | |
| ```python | |
| import asyncio | |
| from crawl4ai import AsyncWebCrawler, CacheMode | |
| from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator | |
| async def on_browser_created_hook(browser): | |
| # Access the default context and create a page | |
| context = browser.contexts[0] | |
| page = await context.new_page() | |
| # Navigate to the login page | |
| await page.goto("https://example.com/login", wait_until="domcontentloaded") | |
| # Fill in credentials and submit | |
| await page.fill("input[name='username']", "myuser") | |
| await page.fill("input[name='password']", "mypassword") | |
| await page.click("button[type='submit']") | |
| await page.wait_for_load_state("networkidle") | |
| # Now the site sets tokens in localStorage and cookies | |
| # Export this state to a file so we can reuse it | |
| await context.storage_state(path="my_storage_state.json") | |
| await page.close() | |
| async def main(): | |
| # First run: perform login and export the storage_state | |
| async with AsyncWebCrawler( | |
| headless=True, | |
| verbose=True, | |
| hooks={"on_browser_created": on_browser_created_hook}, | |
| use_persistent_context=True, | |
| user_data_dir="./my_user_data" | |
| ) as crawler: | |
| # After on_browser_created_hook runs, we have storage_state saved to my_storage_state.json | |
| result = await crawler.arun( | |
| url='https://example.com/protected-page', | |
| cache_mode=CacheMode.BYPASS, | |
| markdown_generator=DefaultMarkdownGenerator(options={"ignore_links": True}), | |
| ) | |
| print("First run result success:", result.success) | |
| if result.success: | |
| print("Protected page HTML length:", len(result.html)) | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |
| ``` | |
| **Second Run (Reuse Saved State, No Login Needed):** | |
| ```python | |
| import asyncio | |
| from crawl4ai import AsyncWebCrawler, CacheMode | |
| from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator | |
| async def main(): | |
| # Second run: no need to hook on_browser_created this time. | |
| # Just provide the previously saved storage state. | |
| async with AsyncWebCrawler( | |
| headless=True, | |
| verbose=True, | |
| use_persistent_context=True, | |
| user_data_dir="./my_user_data", | |
| storage_state="my_storage_state.json" # Reuse previously exported state | |
| ) as crawler: | |
| # Now the crawler starts already logged in | |
| result = await crawler.arun( | |
| url='https://example.com/protected-page', | |
| cache_mode=CacheMode.BYPASS, | |
| markdown_generator=DefaultMarkdownGenerator(options={"ignore_links": True}), | |
| ) | |
| print("Second run result success:", result.success) | |
| if result.success: | |
| print("Protected page HTML length:", len(result.html)) | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |
| ``` | |
| **What’s Happening Here?** | |
| - During the first run, the `on_browser_created_hook` logs into the site. | |
| - After logging in, the crawler exports the current session (cookies, localStorage, etc.) to `my_storage_state.json`. | |
| - On subsequent runs, passing `storage_state="my_storage_state.json"` starts the browser context with these tokens already in place, skipping the login steps. | |
| **Sign Out Scenario:** | |
| If the website allows you to sign out by clearing tokens or by navigating to a sign-out URL, you can also run a script that uses `on_browser_created_hook` or `arun` to simulate signing out, then export the resulting `storage_state` again. That would give you a baseline “logged out” state to start fresh from next time. | |
| --- | |
| ### Conclusion | |
| By using `storage_state`, you can skip repetitive actions, like logging in, and jump straight into crawling protected content. Whether you provide a file path or a dictionary, this powerful feature helps maintain state between crawls, simplifying your data extraction pipelines. |