# Starting profiles

We require you to send a separate request to start the profile. Basically, for a few reasons:

  1. To lock the profile, so that others won't be able to use it while your session is active
  2. To disallow you using the profile, if it is being used by someone else, or if it was deleted, or if there is a problem with some dependencies like proxy.

If you do not want to lock the profile, or want to use it even if it was locked by someone else - it's possible, but you still have to send this request, just with other parameters.

# What is a profile lock

We assign a special key - profileLock - to each profile session (except those run without locking). This is a pseudo randomly generated UUID string, e.g. 4729de92-e283-4834-9e70-1d5913c4cf4d.

If the session is currently active, i.e. the profile was started and wasn't stopped, then the folder upload and cookie import is allowed only if this exact key is provided in the corresponding request. That way we know, that the person uploading folder and cookies is the one who actually has been using the profile since it was started.

Simply saying - if you want to use the locking mechanism, you need to provide the current profileLock to be able to upload profile folder. And profile start is necessary to acquire this lock.

# Request

The request is POST https://api.surfinite.com/profiles/{profile_id}/start and you should check it out in API reference. We will just describe the params and responses in depth here.

So, apart from api_key, you have the option to set two URL params: use_lock and current_lock.

  1. The first one, use_lock (true by default), indicates whether you want to lock the profile (and be rejected if it already is). If the request succeeds, you will get a JSON response, containing a profileLock and browserKey for your session.
  2. The second one, current_lock, is an optional parameter. If the profile is currently being used by someone else, you can actually override their session by providing its profileLock. You can override any session as an API Key owner, but more on that later.

The success (200) response is a JSON object:

{ 
  "browserKey": "key_to_start_browser", 
  "profileLock": "lock_of_current_session" 
}

The browserKey is non-nullable parameter. But the profileLock will be absent if you set use_lock=false.

You can find error responses in API reference.

# Browser key

Browser key is another way for us to identify your session. The thing is that profileLock might be absent, so we would not know who is starting the profile. But the browserKey will always be there. You only need this parameter to start the browser and it is valid for 60 minutes after the profile was started (so you can close and start the browser multiple times during this hour without having to send a new start request).

# Code example

val apiUrl = "https://api.surfinite.com"

val profileId = "my_profile_id"
val apiKey = "MY_API_KEY"
val useLock = true

val url = "$apiUrl/profiles/$profileId/start?use_lock=$useLock&api_key=$apiKey"

val client = HttpClient(CIO) { expectSuccess = true }
val responseString = runCatching {
    client.post(url).bodyAsText()
}.getOrElse { it: Throwable ->
    when (it) {
        is ClientRequestException -> {
            when (it.response.status) {
                HttpStatusCode.Unauthorized -> println("Unauthorized: bad api key") // 401
                HttpStatusCode.NotFound -> println("Profile not found") // 404
                HttpStatusCode.Conflict -> { // 409
                    // Response body is a JSON object containing the profile lock,
                    // so you can resend the request with it and override current session
                    println("Profile is already being used")
                }
                HttpStatusCode.Gone -> { // 410
                    // The profile is in your Recycle Bin, you can still restore it
                    println("The profile was deleted")
                }
                HttpStatusCode.UnprocessableEntity -> println("Profile is synchronizing") // 422
                HttpStatusCode.Locked -> { // 423
                    // Response body is a JSON object containing the profile lock,
                    // so you can resend the request with it and override current session
                    println("Your current_lock parameter was incorrect")
                }
                HttpStatusCode.FailedDependency -> { // 424
                    // Profile had a proxy assigned from the Proxy List, and it got deleted.
                    // Update the profile with a new proxy and then restart the profile
                    println("Assigned proxy does not exist")
                }
                else -> println("Server responded with: ${it.response.status}")
            }

            // Just print the body in case it contains a useful message
            println(it.response.bodyAsText())
        }
        is TimeoutException -> println("Request timed out")
        is ConnectException -> println("Server does not respond or you have no internet")
        else -> {
            // Unknown error
            it.printStackTrace()
        }
    }
    return
}

val responseJSON = Json.parseToJsonElement(responseString).jsonObject
val browserKey = responseJSON["browserKey"]!!.jsonPrimitive.content
val profileLock = responseJSON["profileLock"]!!.jsonPrimitive.content

println("Got the browserKey: $browserKey and profileLock: $profileLock")