Uplink provides specialized methods for waiting for users to complete authentication on their devices. Since real users log themselves in on real mobile devices, you avoid the complexity of bot detection, CAPTCHA solving, and proxy servers entirely.
The Uplink Advantage : Users authenticate themselves on their own devices. No credential management, no CAPTCHA solvers, no expensive proxies, and no bot detection issues. Simply wait for the user to complete authentication, then automate the rest.
Methods
page.authenticate()
Navigates to a URL and waits for authentication to complete.
page . authenticate (
startURL : string ,
authEvaluator : AuthEvaluator ,
options ?: AuthenticateOptions
): Promise < AuthStatus >
Parameters:
startURL: URL to navigate to for authentication
authEvaluator: Function that checks if authentication is complete
options (optional): Authentication options
AuthEvaluator:
type AuthEvaluator = ( page : Page ) => boolean | Promise < boolean >
Options:
interface AuthenticateOptions {
timeout ?: number // Timeout in milliseconds (default: 90000)
}
Returns: Promise<AuthStatus> - Either 'authenticated' or 'aborted'
Examples:
// Wait for session cookie
const status = await page . authenticate (
'https://example.com/login' ,
async ( page ) => {
const cookies = await page . cookies ( 'https://example.com' )
return cookies . some ( c => c . name === 'session_token' )
},
{ timeout: 90000 }
)
if ( status === 'authenticated' ) {
console . log ( 'Authentication successful' )
}
// Wait for URL change
const status = await page . authenticate (
'https://example.com/oauth/authorize' ,
async ( page ) => {
const url = await page . url ()
return url . includes ( '/dashboard' )
}
)
page.waitForAuthentication()
Waits for authentication to complete without navigating.
page . waitForAuthentication (
authEvaluator : AuthEvaluator ,
options ?: AuthenticateOptions
): Promise < AuthStatus >
Parameters:
authEvaluator: Function that checks if authentication is complete
options (optional): Authentication options
Returns: Promise<AuthStatus> - Either 'authenticated' or 'aborted'
Example:
// User manually logs in on the device
await page . goto ( 'https://example.com/login' )
// Wait for them to complete authentication
const status = await page . waitForAuthentication (
async ( page ) => {
const url = await page . url ()
return url . includes ( '/dashboard' )
},
{ timeout: 120000 } // 2 minutes
)
if ( status === 'authenticated' ) {
console . log ( 'User logged in successfully' )
}
Complete examples
OAuth flow
async function handleOAuthLogin ( page ) {
const status = await page . authenticate (
'https://app.example.com/oauth/google' ,
async ( page ) => {
// Check if we're back at the app with an auth token
const url = await page . url ()
if ( ! url . includes ( 'app.example.com' )) return false
// Verify we have the auth cookie
const cookies = await page . cookies ( 'https://app.example.com' )
return cookies . some ( c => c . name === 'oauth_token' )
},
{ timeout: 120000 } // Give user 2 minutes to log in
)
if ( status === 'authenticated' ) {
console . log ( 'OAuth login successful' )
return true
} else {
console . log ( 'OAuth login aborted or timed out' )
return false
}
}
const success = await handleOAuthLogin ( page )
if ( success ) {
// Continue with authenticated session
await page . goto ( 'https://app.example.com/dashboard' )
}
Social login
async function socialLogin ( page , provider ) {
const status = await page . authenticate (
`https://example.com/login/ ${ provider } ` ,
async ( page ) => {
// User completes login on social provider's site
// Check for success indicator
const url = await page . url ()
if ( url . includes ( 'example.com/welcome' )) {
return true // Redirected to welcome page
}
// Or check for authentication cookie
const cookies = await page . cookies ( 'https://example.com' )
return cookies . some ( c => c . name === 'auth_session' )
},
{ timeout: 180000 } // 3 minutes for social login
)
return status === 'authenticated'
}
// Try Google login
const success = await socialLogin ( page , 'google' )
console . log ( 'Google login:' , success ? 'success' : 'failed' )
Two-factor authentication
async function waitForTwoFactorLogin ( page ) {
// Navigate to login page
await page . goto ( 'https://example.com/login' )
// User enters their credentials and 2FA code on the device
console . log ( 'Waiting for user to complete login with 2FA...' )
const status = await page . waitForAuthentication (
async ( page ) => {
const url = await page . url ()
return url . includes ( '/dashboard' )
},
{ timeout: 180000 } // Give user 3 minutes to enter credentials + 2FA
)
if ( status === 'authenticated' ) {
console . log ( 'User successfully completed 2FA login' )
return true
}
return false
}
await waitForTwoFactorLogin ( page )
CAPTCHA handling
async function waitForCaptchaLogin ( page ) {
await page . goto ( 'https://example.com/login' )
// User enters credentials and solves CAPTCHA on their device
console . log ( 'Waiting for user to complete login and solve CAPTCHA...' )
const status = await page . waitForAuthentication (
async ( page ) => {
// Check if we've moved past the login/CAPTCHA page
const url = await page . url ()
if ( url . includes ( '/dashboard' )) return true
// Or check for authenticated state indicator
const isAuthenticated = await page . evaluate (() => {
return document . body . classList . contains ( 'logged-in' )
})
return isAuthenticated
},
{ timeout: 300000 } // 5 minutes for user to login + solve CAPTCHA
)
return status === 'authenticated'
}
Session-based authentication
async function checkSession ( page ) {
await page . goto ( 'https://example.com' )
const status = await page . waitForAuthentication (
async ( page ) => {
const cookies = await page . cookies ( 'https://example.com' )
const sessionCookie = cookies . find ( c => c . name === 'session_id' )
if ( ! sessionCookie ) return false
// Optionally validate the session cookie
const isValid = await page . evaluate (() => {
return document . body . classList . contains ( 'logged-in' )
})
return isValid
},
{ timeout: 10000 }
)
return status === 'authenticated'
}
const isAuthenticated = await checkSession ( page )
if ( ! isAuthenticated ) {
console . log ( 'No valid session, need to log in' )
// Proceed with login flow
}
Mobile app authentication
async function appAuthentication ( page ) {
// Navigate to the authentication start page
const status = await page . authenticate (
'https://example.com/app/auth' ,
async ( page ) => {
// Check for mobile-specific auth indicator
const authToken = await page . evaluate (() => {
return localStorage . getItem ( 'auth_token' )
})
if ( ! authToken ) return false
// Verify token is valid
const url = await page . url ()
return url . includes ( '/app/home' )
},
{ timeout: 180000 }
)
if ( status === 'authenticated' ) {
// Get the auth token for API calls
const token = await page . evaluate (() => {
return localStorage . getItem ( 'auth_token' )
})
console . log ( 'Authenticated, token:' , token )
return token
}
return null
}
Retry authentication
async function authenticateWithRetry ( page , maxAttempts = 3 ) {
for ( let attempt = 1 ; attempt <= maxAttempts ; attempt ++ ) {
console . log ( `Authentication attempt ${ attempt } / ${ maxAttempts } ` )
const status = await page . authenticate (
'https://example.com/login' ,
async ( page ) => {
const cookies = await page . cookies ( 'https://example.com' )
return cookies . some ( c => c . name === 'session' )
},
{ timeout: 60000 }
)
if ( status === 'authenticated' ) {
console . log ( 'Authentication successful' )
return true
}
if ( attempt < maxAttempts ) {
console . log ( 'Authentication failed, retrying...' )
await page . goto ( 'https://example.com/logout' )
await new Promise ( resolve => setTimeout ( resolve , 2000 ))
}
}
console . log ( 'Authentication failed after all attempts' )
return false
}
const success = await authenticateWithRetry ( page )
Best practices
Let users handle credentials
With Uplink, users authenticate themselves on their own devices. This eliminates bot detection, CAPTCHA challenges, and the need for proxy servers: // Navigate to login page and wait - user handles the rest
await page . authenticate (
'https://example.com/login' ,
async ( page ) => {
const cookies = await page . cookies ( 'https://example.com' )
return cookies . some ( c => c . name === 'session' )
}
)
// Now automate authenticated actions
Authentication often requires user interaction, so use longer timeouts: const status = await page . authenticate (
url ,
evaluator ,
{ timeout: 180000 } // 3 minutes for complex auth
)
Check multiple indicators
Verify authentication using multiple methods: async ( page ) => {
const url = await page . url ()
const cookies = await page . cookies ( 'https://example.com' )
return url . includes ( '/dashboard' ) &&
cookies . some ( c => c . name === 'session_token' )
}
Handle aborted authentication
Always handle the aborted case: const status = await page . authenticate ( url , evaluator )
if ( status === 'aborted' ) {
console . log ( 'User closed authentication or it timed out' )
// Handle gracefully
}
Extract and store authentication tokens for later use: if ( status === 'authenticated' ) {
const token = await page . evaluate (() => {
return localStorage . getItem ( 'token' )
})
// Store token for API calls
}