
Appium Sessions — Python
Appium Sessions — Python
Configuring and Launching Mobile Sessions

The first step in any mobile app automated test is to create an Appium session. This is more or less the same as what we do with Selenium to create a browser session, but there are some important differences.

In a prior post, we got all our system dependencies set up and installed for Appium. We‘ve also figured out how to install Python. Now let’s learn how to configure and launch an Appium session.
Project Setup
For our Python scripts, in addition to Appium and Selenium setup that we use to run the code, we also need a development environment. Hence, let’s set up our local code environment so that we can begin to write test scripts. We’re going to start a project from scratch here, and you can build out this project over the course of automating your test framework, as you see fit or as the need arises.
All right, the first thing we want to do is to create a directory somewhere on our system for our project to live. Let’s create a directory called appium_testing on the desktop with the mkdir command. It doesn't really matter where it is or what it's called, so put yours wherever you wish. I'll open up a terminal and navigate to it with cd, so I am inside it, from the command line:

There are no files in this newly created directory, as the ls command I tried above did not return any output. If we choose to navigate to this folder later, we can cd into it directly as follows:
cd ~/Desktop/appium_testing
If you’re on Windows, the cd command will work, but you’ll need to use a Windows-style path, like cd C:\Users\user\appium_testing or similar. Now I'm in my code directory, and I'm going to make a new directory inside of it.
At this point we need to get the Appium and Selenium client libraries installed so that we can use them to write Python test scripts. We’re going to do this by using the pip3 command for downloading Python packages and making them available in our environment. If you're a Python developer and know about tools like virtualenv or pyenv that help keep Python projects in their own environments, feel free to create an environment now and use it, but it’s not necessary. For example, if you use pyenv, proceed with the following commands:
pyenv virtualenv appium_testing
pyenv activate appium_testing
Now, whether we are in a virtual environment or are just using our normal environment, we can use the pip3 command to install the appropriate client libraries and dependencies:
pip3 install selenium Appium-Python-Client
This command will install both the Selenium client and the Appium client, all in one go. So I’ll run it and watch everything download.

Great, that’s all installed! Let’s make sure it got installed correctly by starting up a Python interpreter on the command line with python3:

This puts us into a little shell within a shell, where we can run Python commands. The command we’re going to run is:
from selenium import webdriver

And we’ll hit Return/Enter. If that line completes without any errors, then Selenium has been installed successfully. To quit this interpreter, we can type exit() and then hit Return or Enter, depending whether we’re on a Mac or Windows respectively.

Now we’re going to do it again for Appium:
from appium import webdriver

And again, if this is working, we’ll see no output. Then we’ll exit again.

At this stage, our project setup is complete and verified. Let’s now proceed to the core subject of this demo — the Appium sessions!
Appium Session Requirements
What we need to have on hand in order to start an Appium session goes a little bit beyond what we need for a Selenium session. Let’s have a look at what it is.

A running Appium server to connect to.
We need to have an Appium server running (or we need to have one on the Internet we’re connecting to). The Appium Python client will not start the Appium server or configure Appium drivers for us.
A copy of an app build somewhere on the machine Appium is running on (or connected via network), otherwise app already installed on the device.
Then we need to have a copy of our app handy so that Appium can install and launch it on the mobile device. This is a bit different from a web test. With Selenium, it’s assumed that any app is already going to be hosted on a server somewhere, and we’re just going to provide the URL so the browser can navigate to the app to begin testing. With Appium, there are several ways we can start a session.
- If the app is already on our test device, then we don’t need to have another copy of it. We can just direct Appium to launch it.
- But the more common setup is where we have a copy of our app, let’s say it’s the latest build that’s been created by the dev team.
As long as it is somewhere on the same machine where Appium is running, we can give Appium a path to this app, and Appium will install it and launch it for us. This is also preferable because it allows Appium to determine information about the app that we would otherwise have to provide specifically. We’ll talk more about what format the app needs to be in shortly.
A device under test connected and running.
It’s best to make sure that the device we want to automate is already connected or running. With Appium, we can automate either virtual devices, meaning emulators and simulators, or real physical devices. In this post we’re going to focus on launching emulators and simulators in our examples since they are easier to obtain. Also, setting up a real iOS device for testing can be quite challenging due to Apple’s strict app security requirements.
When running our code remotely with a cloud provider, we’re running them on the provider’s platform, which consists entirely of real devices. We usually also have real devices at our disposal or a local device farm set up for for the purpose of testing real-world user scenarios. As a mobile tester, you’ve most likely already gotten the taste of both real and virtual devices. But for the purposes of this point, it’s a good idea to have the specific device you want to automate already launched.
Capabilities that tell Appium about our app, device, etc.
Finally, the capabilities required to start an Appium session go beyond the simple browserName and browserVersion required for Selenium sessions. We'll look in detail at which are required in a bit.
App Requirements

Nothing special for web apps. Simply navigate to the URL. But for our mobile test app, we need a binary that meets certain requirements.
Let’s talk about the format that our mobile app needs to be in to automate it with Appium. Of course, if we’re automating a web app, we can just use the mobile browser to navigate to the site, and nothing additional is required. But if we’re automating a native or hybrid app, then we need the app binary. For our demo test app, you can download these files from a public repository. For other apps, you need to make sure they conform to these rules:
App should be a debug or development build (not a production or a release build).
The app should be a debug or development build. It’s not possible to install a production or release build onto a virtual device. Whoever generates builds of your app should know how to do this, if it’s not you doing it yourself.
App should be in .apk format for Android or .app (or .app.zip) format for iOS virtual devices. The .ipa format is used for real iOS device testing.
The app should be in .apk format for Android, or .app format for iOS. There's another format for iOS, namely .ipa, but this is really only used for installing apps on real devices. One thing to note is that .app files for iOS are actually directories, not single files. So to transport them around the internet, it's customary to zip them up, so that the actual extension we often see is .app.zip. This is an extension that Appium knows how to work with, and this is the extension we download the demo app with.
App needs to be on the same file system as Appium, or accessible over internet/intranet.
The app must either be located on the same system as the one running Appium, or somewhere on the internet accessible via a URL. This means that if we’re using a cloud service, there’s usually a specific method for pre-uploading our app and then referring to it, since the cloud service won’t have any access to our local filesystem where the app is sitting.
Session Capabilities
Now let’s cover the capabilities required to start any Appium session. But before that, let’s get a grasp of what a session is.
Appium Client-Server Architecture

Appium has a client-server architecture, which means that every Appium command gets sent over the network as an HTTP request. We want our test to proceed in a logical manner, one step after the other, finding elements and interacting with them. What this means is that our Appium client code needs to attach something to every request to let the Appium server know we are dealing with the same test. That something is called a session ID and the Appium server will associate any commands sent in with that ID as belonging to the same session.
Session IDs
The session ID is the thing which is used to group automation commands together and to allow a test to proceed one step at a time.

The various commands that need to follow one another in the course of a particular test all share the same session ID. What all of this means is that before we begin our automation, we need to start an Appium session. And when we’re done, we need to stop an Appium session. We’ll discuss how exactly to do that shortly.
For now, let’s talk about telling Appium what kind of session we want. We can start many different kinds of Appium sessions. We can start a session on an IOS simulator, for example. Or we could start one on an Samsung Android device physically plugged into our computer. So to make sure we’re automating the right kind of thing for our test, we need to tell Appium what it is we want. We do this in a form of session parameters known as capabilities.
Capabilities
Capabilities are essentially a set of keys and values that get wrapped up into an object and sent to the Appium server during session initialization. There are a lot of capabilities that Appium supports. Some capabilities are generic and take effect in any platform Appium supports. Other capabilities are platform-specific, or even driver-specific.

We encounter a few different capabilities throughout the course of testing. However, there’s a minimal set of capabilities which is required to start an Appium session on any native mobile app, and those should always be included. These capabilities are:

1. platformName: platform to automate (iOS, Android)
The first required capability is called platformName. This is a capability you might recall from Selenium. With Appium it’s a bit more important. It tells Appium the name of the platform we want to automate. The value here should be a string noting the mobile platform we want to test on. Usually, it’s either iOS or Android.
2. platformVersion: version of platform (17.4)
The next one is platformVersion. This is a string denoting the version of the mobile operating system (iOS or Android) that we want to automate. For example, if you’re working with IOS it could be 17.0 or 17.4. This helps Appium to target the right device and give us an error if it can't find a connected device at the appropriate version.
3. deviceName: type of device to automate (iPhone 15)
Third, a capability that does not exist in the web world is the deviceName capability. This is a string that lets Appium know what manner of device it should connect to. It could be for example, the iPhone 15 simulator, in which case Appium will look for or start that particular IOS simulator for running the test. Or if we want to simply connect to an already running Android emulator, we could choose a value of Android emulator. Basically, it gives the Appium server information about the specific device we want to automate. For example, a value for this capability might be iPhone 13 mini or SM-G975F.
4. automationName: driver to automate (XCUITest, UiAutomator2)
Fourth, we need the automationName capability. This tells Appium the name of the driver we want to use for the session. When we set up Appium earlier, we ran the commands to download the UiAutomator2 driver and the XCUITest driver. The output of those install commands lets us know the specific name that can be used with this capability.


5. app: path to our app or browserName:
Finally, we need to tell Appium something about the app we want to automate. Here we have a choice of capability to use — browserName or app.
browserName: If we just want to automate a browser, in order to test a website, we can use the browserName capability, with a value of Safari on iOS or Chrome on Android.
app: But if we want another kind of app, we need to use the app capability - a path to the prebuilt binary version of the app that we want to test. For Android, the app extension will be .apk, and for IOS the app extension will be .app or .app.zip and it needs to be zipped. And the value should be one of the following:
- An absolute local path to the .app (.app.zip) or .apk file for iOS or Android respectively. For example, /users/foo/apps/app.apk.
- A fully qualified URL to a downloadable zipped version of the app.
With the combination of these 5 capabilities, Appium will know how to start a session for us.
Starting and Stopping a Session
Let’s now switch over for some hands-on experimentation with starting sessions. Here we are in the terminal, in our code project directory. I’m going to now create a new directory called mobile, in the main project directory, to hold all the mobile examples:
mkdir mobile
cd mobile
And now I’m in that directory as well. It’s time to go to an editor, such as PyCharm, VSCode or similar.

iOS Session
We’re going to make a new file called sessions_ios.py inside the mobile directory this time. The first thing we want to do is import the Appium client so we can use it. This is similar but slightly different than importing the Selenium client. For Selenium, we do from selenium import webdriver, but now we are going to do:
from appium import webdriver
This ensures we’re using a client that has all of the Appium command extensions we might need to use. Now, we need to figure out how to get the absolute path to the app we want to test.
I’m going to start an iOS session in this file, so I need to somehow find the iOS version of The App. I could just create a string variable holding the path to that downloaded file, if I know where it is. But it’s a bit more convenient to locate the app close by and refer to it in terms relative to my project. So I’m going to copy both the apps into this mobile directory. And now I need to teach my script where this directory is. To accomplish that, we should first import a module called path from Python's os library:
from os import path
CUR_DIR = path.dirname(path.abspath(__file__))
With it, we can create a variable designed to hold the absolute path to the current directory. We use a combination of path.dirname and path.abspath for this, as well as the magic variable __file__ which always refers to the file where it is encountered.
Now, we can use another path function called join to join the path of the current directory to the filename of the iOS app:
APP = path.join(CUR_DIR, 'TheApp.app.zip')
The end result of this will be that the absolute path of our app file is in this APP variable. In lieu of the absolute path, it might be a URL where the same .app.zip file could be downloaded. For example:
APP = "https://github.com/appium-pro/TheApp/releases/download/v1.12.0/TheApp.app.zip"
If you choose the URL option, make sure to delete the path module import and the CUR_DIR variable.
Notice that I'm using all caps for these variables. It's not necessary to do this and it has no effect on the Python code whether we use all caps or not. But it's a sort of convention to define constant values that will be used globally throughout a script with all caps. It helps to distinguish them from variables that we might define and discard along the way.
The next thing that’s convenient to define up top is the location of the Appium server we’re going to use. And that makes now a great opportunity to start that Appium server. So I’m going to open up a new terminal window, and start Appium there:

It’s as simple as running the appium command, and we'll see Appium's startup info to know that it's listening. We’d also pay attention to the port that Appium is running on, which is the default port of 4723. We can change this using a command line flag if we want to for some reason, but we'll leave it as is for now. Looking at Appium's startup printout, I also notice that I have the XCUITest and UiAutomator2 drivers installed, and Appium even tells me what automationName capabilities to use to target them. That's good to know too. It’s time to get back to our code.
Now that we know Appium is running on our localhost interface at port 4723, we can encode this knowledge in a variable:
APPIUM = 'http://localhost:4723'
This isn’t mandatory, but I like to put all data strings like this up at the top of the file, so if I ever need to change them, it’s easy to do in one place.
We also need to define our capabilities before we start the Appium server.
CAPS = {
"platformName": "iOS",
"appium:options": {
"platformVersion": "17.4",
"deviceName": "iPhone 15 Pro Max",
"automationName": "XCUITest",
"app": APP
}
}
I’m including all 5 capabilities we talked discussed before. Setting platformName to iOS, platformVersion to 17.4 (which is the latest version I have while recording this), setting the deviceName to iPhone 15 Pro Max, and then using the appropriate automationName and app capabilities. For app we just set the value to our APP variable, which is handy.
One note before we go any further. Depending on when you’re reading this post, the version of Xcode you downloaded might not have come with iOS 17.4. So you have two options for how to fix this. The first option is to go into Xcode’s preferences and download the iOS 17.4 SDK. The second option is to adjust this script to use a version of the iOS SDK which you do have downloaded. Which way you go is up to you. But if you run this script with a version you don’t have, you’ll get an error. Happily, if you read the Appium logs when the error occurs, the Appium logs will also show you which iOS SDK version is available, so you can make sure to use that one.
You may have noticed that the capabilities object contains a distinct “appium:options” key. Appium v2 introduced the option of wrapping up all Appium-related capabilities into one object capability, appium:options. We can bundle together anything that we’d normally put an appium: prefix on into this one capability. As a rule of thumb, W3C WebDriver capabilities, such as the platformName, do not require this prefix.
One more thing to do is importing AppiumOptions, creating an OPTIONS variable and passing in our capabilities to the options’ load_capabilities() method.
from appium.options.common import AppiumOptions
OPTIONS = AppiumOptions().load_capabilities(CAPS)
All right, once we have our capabilities and options defined, all that’s left is to start the session. At this point, it’s exactly like starting a browser session, except we’re going to use webdriver.Remote rather than one of the built-in browser driver classes.
driver = webdriver.Remote(
command_executor=APPIUM,
options=OPTIONS
)
driver.quit()
In this code example, once the instantiation of the driver is complete, we have ourselves an automation session. And we can do whatever we want with it, for example, find elements and interact with them. But the safest thing to learn first, is how to quit the session when we’re done. To do that, we simply call the quit() method on our driver object.
It’s important to always quit sessions cleanly, because it tells Appium that it can freely reallocate resources for other tests, for example access to a particular device or emulator. No tester needs zombie sessions clogging up the machine!
Again, all we’re doing is stopping and starting a session, so this is a pretty short script. Let’s try and run it. I’ve got my Appium server running and the script ready, so I’ll head to my terminal and run it from the mobile directory:
python3 sessions_ios.py
Once we kick this off, the first thing we’ll see is that the Appium server logs have started to go wild. These logs are describing everything Appium or the XCUITest driver are doing in order to handle the new session request. I’m also noticing that an iOS simulator is starting. If you didn’t already have a simulator open with what happened to be an iPhone 15 Pro Max sim, then a new one will pop up (feel free to close any of the other ones). The simulator takes a little while to boot.
The next thing you might notice is a lot of nothing. It may look as though the simulator sits and does nothing for a long time. And if we look at the Appium log, we might see a bunch of lines that keep repeating for what feels like a long time. The reason for this is that the first time we run the XCUITest driver, it needs to build some of its internal components in order to handle the automation session. Depending on your machine, this can take several minutes to complete. So just sit tight. For future sessions, the existing build will be used, and the existing simulator will be used, so they’ll start in seconds rather than minutes.
But eventually, if all goes well, and while we’re keeping an eye on the simulator we should see the app pop up and then go away. And if all goes well, as we examine the output of our python3 command, we should see nothing. That means we successfully started a session on iOS. If you got some other kind of error, first try reading the error message, and then try looking at the Appium logs, scrolling back until you see a message that might be helpful. There is often relatively specific instruction in the Appium logs to help deal with fixable errors.
🎥 iOS Execution: https://youtu.be/oCcQXO2cQ3s

Android Session
So that’s it for iOS. Now let’s make sure we can start an Android session. Back in the code editor, let’s copy all of the sessions_ios.py file, create a new file called sessions_android.py, and paste in the contents, so we're not starting from scratch. What do we need to adjust here in order to make our session run on Android? The first thing is that we need to modify our APP location. We're not dealing with an iOS app anymore, so we should change the filename to TheApp.apk:
APP = path.join(CUR_DIR, 'TheApp.apk')
And then, of course, we should update our capabilities to refer to all the Android-specific stuff we need:
CAPS = {
"platformName": "Android",
"appium:options": {
"platformVersion": "14.0", # optional
"deviceName": "Android Emulator",
"automationName": "UiAutomator2",
"app": APP
}
}
Here we are updating the platform to “Android”, the version to “14.0”, the deviceName to “Android Emulator”, and the automationName to “UiAutomator2”. The same thoughts about platformVersion apply here as for iOS. If you’re using an emulator or device running a different version of Android, change this capability to match suit. And if you run into problems with that, there’s a little hack — on Android, it doesn’t actually matter if you don’t include a platformVersion. If you don’t include one, Appium will just happily use the first connected device. So as long as we make sure that we just have one device connected, namely our emulator, then we can safely omit this capability for Android.
The rest of the script can stay the same, because it’s just starting and stopping the session. So, let’s put this to the test. Make sure to to have the Appium server running and double-check that an Android virtual device (emulator) is also running. Now let’s head to the terminal, so we can run this script:
python3 sessions_android.py
And off we go! Similar to iOS, the first time we run a session, it can take a little while for the driver to build anything it needs to. But eventually we will see our app under test pop up and then go away. This means everything worked, so long as we don’t get any error output from our Python script.
🎥 Android Execution: https://youtu.be/Mxc1xith-To?si=CQM_qQXNNuoJNv_z
And indeed, it looks like all is well here. So this is how we start and stop sessions on iOS and Android platforms using Appium!
Starting sessions on real devices is a little different because we have to include some more information about which devices specifically to use, but we’ll get to that in its due time.
So that’s it. That’s how we tell Appium to start sessions on a particular platform and device, and how to stop the session when we’re done with our automation.

Stay tuned to learn more about the Appium automation API.
Happy testing and debugging!
I welcome any comments and contributions to the subject. Connect with me on LinkedIn, X , GitHub, or IG.

Test App: https://github.com/appium-pro/TheApp/releases
Demo Code: https://github.com/lana-20/appium-sessions
Appium Capabilities: https://appium.io/docs/en/2.0/guides/caps/
Demo Videos: https://www.youtube.com/playlist?list=PLbWhm4uo5suuNrfAL30HsSkPkGAMRkcon