Get localStorage, sessionStorage and cookies from logins for usage in other actors.
Get localStorage, sessionStorage and cookies from logins for usage in other actors.
This actor can help you (re)use logged in sessions for your website and serivces, abstracting away the need for developing your own login mechanism. It uses a named session storage, so you when you request a new session, it will be readily available. It's tailored to work seamlessly on Apify platform and other actors.
It's more low-level than other actors, but it tries to cover the most common use cases like:
You may call directly from your actor, or use the INPUT.json
to create a task or scheduled to keep seeding your session storage with new sessions. It cannot deal with 2FA or captchas (yet).
1// in your actor 2const storageName = 'session-example'; 3 4const call = await Apify.call('pocesar/login-session', { 5 username: 'username', 6 password: 'password', 7 website: [{ url: 'http://example.com' }], // the RequestList format 8 cookieDomains: [ 9 "http://example.com" 10 ], 11 sessionConfig: { 12 storageName, 13 maxAgeSecs: 3600, 14 maxUsageCount: 10, 15 maxPoolSize: 120 16 }, 17 steps: [{ 18 username: { 19 selector: "input#email", // the input that receives the username 20 timeoutMillis: 10000 // optional timeout in ms 21 }, 22 password: { 23 selector: "input#password" // the input that receives the password 24 }, 25 submit: { 26 selector: "input[type=\"submit\"]", // the button that executes the login 27 }, 28 failed: { 29 selector: "[role=\"alert\"],#captcha", // usually an error that tells the login failed 30 timeoutMillis: 10000 // optional timeout in ms 31 }, 32 waitForMillis: 15000 // optional "sleep" in ms to consider the page as "settled" 33 }] 34}); 35 36const { session, error } = call.output; 37 38// if it fails, the error will be filled with something 39// otherwise, the session will have the Session parameters, that can be 40// instantiated manually using `new Apify.Session({ ...session, sessionPool })` 41 42// load the session pool from the storage, so it has our new 43// session. this might change in the future 44const sessionPool = await Apify.openSessionPool({ 45 persistStateKeyValueStoreId: storageName 46}); 47 48const sessionJustCreated = sessionPool.sessions.find(s => s.id === session.id); 49 50/** 51 * the complete Cookie string for usage on the header 52 */ 53sessionJustCreated.getCookieString('http://example.com'); 54 55/** 56 * contains the User-Agent used for the login request. 57 * the same userAgent must be set between uses so there's no 58 * conflict and blocks. Set this as your User-Agent header 59 **/ 60sessionJustCreated.userData.userAgent; 61 62/** 63 * the proxyUrl used, can be empty. 64 * Set this as your proxyUrl parameter in crawlers. 65 * 66 * This might be undefined if you didn't use any proxies 67 */ 68sessionJustCreated.userData.proxyUrl; 69 70/** 71 * object containing any sessionStorage content, useful for JWT tokens. 72 * Useful for using in PuppeteerCrawler 73 */ 74sessionJustCreated.userData.sessionStorage; 75 76/** 77 * object containing any localStorage content, useful for JWT 78 * tokens. Useful for using in PuppeteerCrawler 79 */ 80sessionJustCreated.userData.localStorage;
You can login locally, executing the login-session actor on your machine, make sure you're logged in to the platform using apify login
and using forceCloud
input option, like this:
1{ 2 "username": "username", 3 "password": "s3cr3tp4ssw0rd", 4 "website": [{ "url": "https://example.com/" }], 5 "sessionConfig": { 6 "storageName": "example-login-sessions" // need to use this 7 }, 8 "steps": [ 9 { 10 "username": { "selector": "#email" }, 11 "password": { "selector": "#password" }, 12 "submit": { "selector": "input[type=\"submit\"]" }, 13 "success": { "selector": ".main-menu", "timeoutMillis": 10000 }, 14 "failed": { 15 "selector": ".login.error", 16 "timeoutMillis": 10000 17 }, 18 "waitForMillis": 30000 19 } 20 ], 21 "cookieDomains": ["https://example.com"], 22 "proxyConfiguration": { 23 "useApifyProxy": false 24 }, 25 "forceCloud": true // this forces the login to be saved on platform Storage (https://my.apify.com/storage#/keyValueStores) 26}
Place this in your apify_storage/key_value_stores/default/INPUT.json
file, then run locally:
$ apify run --purge
The session will be created in your Apify platform account, under the storageName
you provided, but using your local IP.
Using this, you're able to avoid PIN requests and security checkpoint screens.
Here are some real-life examples of INPUT.json that you may use:
1{ 2 "username": "username", 3 "password": "password", 4 "website": [{ "url": "https://accounts.google.com/signin/v2/identifier?service=mail&passive=true&flowName=GlifWebSignIn&flowEntry=ServiceLogin" }], 5 "cookieDomains": [ 6 "https://mail.google.com", 7 "https://accounts.google.com", 8 "https://google.com" 9 ], 10 "steps": [{ 11 "username": { 12 "selector": "#identifierId" 13 }, 14 "submit": { 15 "selector": "#identifierNext" 16 }, 17 "success": { 18 "selector": "input[type=\"password\"]", 19 "timeoutMillis": 10000 20 }, 21 "failed": { 22 "selector": "#identifierId[aria-invalid=\"true\"],iframe[src*=\"CheckConnection\"]" 23 }, 24 "waitForMillis": 30000 25 }, { 26 "password": { 27 "selector": "input[type=\"password\"]" 28 }, 29 "submit": { 30 "selector": "#passwordNext", 31 "timeoutMillis": 15000 32 }, 33 "failed": { 34 "selector": "input[type=\"password\"][aria-invalid=\"true\"],iframe[src*=\"CheckConnection\"]", 35 "timeoutMillis": 5000 36 }, 37 "success": { 38 "selector": "link[href*=\"mail.google.com\"]", 39 "timeoutMillis": 10000 40 }, 41 "waitForMillis": 30000 42 }] 43}
1{ 2 "username": "username", 3 "password": "password", 4 "website": [{ "url": "https://www.facebook.com/" }], 5 "cookieDomains": [ 6 "https://facebook.com" 7 ], 8 "steps": [{ 9 "username": { 10 "selector": "#login_form [type=\"email\"]" 11 }, 12 "password": { 13 "selector": "#login_form [type=\"password\"]" 14 }, 15 "submit": { 16 "selector": "#login_form [type=\"submit\"]" 17 }, 18 "success": { 19 "selector": "body.home", 20 "timeoutMillis": 10000 21 }, 22 "failed": { 23 "selector": "body.login_page,body.UIPage_LoggedOut", 24 "timeoutMillis": 10000 25 }, 26 "waitForMillis": 30000 27 }] 28}
1{ 2 "username": "username", 3 "password": "password", 4 "website": [{ "url": "https://twitter.com/login" }], 5 "cookieDomains": [ 6 "https://twitter.com" 7 ], 8 "steps": [{ 9 "username": { 10 "selector": "h1 ~ form [name=\"session[username_or_email]\"]", 11 "timeoutMillis": 2000 12 }, 13 "password": { 14 "selector": "h1 ~ form [name=\"session[password]\"]", 15 "timeoutMillis": 2000 16 }, 17 "submit": { 18 "selector": "h1 ~ form [role=\"button\"][data-focusable]" 19 }, 20 "success": { 21 "selector": "h2[role=\"heading\"]", 22 "timeoutMillis": 10000 23 }, 24 "failed": { 25 "selector": "h1 ~ form [role=\"button\"][disabled]", 26 "timeoutMillis": 10000 27 }, 28 "waitForMillis": 30000 29 }] 30}
1{ 2 "username": "username", 3 "password": "password", 4 "website": [{ "url": "https://instagram.com" }], 5 "cookieDomains": [ 6 "https://www.instagram.com" 7 ], 8 "steps": [{ 9 "username": { 10 "selector": "input[name=\"username\"]", 11 "timeoutMillis": 10000 12 }, 13 "password": { 14 "selector": "input[name=\"password\"]", 15 "timeoutMillis": 10000 16 }, 17 "submit": { 18 "selector": "button[type=\"submit\"]" 19 }, 20 "success": { 21 "selector": "img[alt=\"Instagram\"]", 22 "timeoutMillis": 10000 23 }, 24 "failed": { 25 "selector": "#slfErrorAlert", 26 "timeoutMillis": 5000 27 }, 28 "waitForMillis": 30000 29 }] 30}
1{ 2 "username": "username", 3 "password": "password", 4 "website": [ 5 { 6 "url": "https://www.linkedin.com/login?fromSignIn=true&trk=guest_homepage-basic_nav-header-signin" 7 } 8 ], 9 "steps": [ 10 { 11 "username": { 12 "selector": "#username" 13 }, 14 "password": { 15 "selector": "#password" 16 }, 17 "submit": { 18 "selector": ".login__form_action_container button" 19 }, 20 "success": { 21 "selector": ".authentication-outlet,.launchpad-cp-enabled", 22 "timeoutMillis": 15000 23 }, 24 "failed": { 25 "selector": ".form__input--error,.login__form,.pin-verification-form", 26 "timeoutMillis": 15000 27 }, 28 "waitForMillis": 30000 29 } 30 ], 31 "cookieDomains": ["https://www.linkedin.com"] 32}
maxAgeSecs
greater than this numberExample form is in https://now-h3p8398gc.now.sh
Apache 2.0
Yes, if you're scraping publicly available data for personal or internal use. Always review Websute's Terms of Service before large-scale use or redistribution.
No. This is a no-code tool — just enter a job title, location, and run the scraper directly from your dashboard or Apify actor page.
It extracts job titles, companies, salaries (if available), descriptions, locations, and post dates. You can export all of it to Excel or JSON.
Yes, you can scrape multiple pages and refine by job title, location, keyword, or more depending on the input settings you use.
You can use the Try Now button on this page to go to the scraper. You’ll be guided to input a search term and get structured results. No setup needed!