How to Get Started with Code (Python) on Zapier#

Looking for Javascript instead of Python? Visit our Code (Javascript) documentation.


With Zapier's Code action you can extend our platform to do just about anything using one of the simplest programming languages available - Python! Run code in response to any trigger that Zapier supports.

Some example use cases include:

  • Transform incorrect dates or convert between other data types.
  • Use custom regular expressions to extract extra data like emails or tracking numbers from large text blobs.
  • Make an extra API call to a different service with requests without building a full dev app.
  • Augment data from a trigger with extra data from some other source (either generated or external API).
  • Anything else you can dream up!

Warning - this is advanced stuff! You probably need to be a programmer to use this - though you are welcome to play with it. Technical support for bugs in your code is not provided!

How does it work?#

The environment is vanilla Python 3.7.2 (2.7.10 for Zaps made before 2019-01-24). Your script is sandboxed and can only run for a limited amount of time and within a limited amount of memory. If you exceed those limits - your script will be killed (you can upgrade to a paid Zapier to increase your limits).

Since the amount of data that might feed into your script might be large or highly dynamic - you'll need to define an input mapping via our GUI. This is a really simple step - the screenshot below shows a very basic example:

Scroll to the examples section to see an assortment of starter scripts.

In your code you will have access to a few variables:

Data Variables#

  • input_data The dictionary of data you did right above your code snippet (not available in triggers). All values will be strings.
  • output A dictionary or list of dictionaries that will be the "return value" of this code. You can explicitly return early if you like. This must be JSON serializable!

Note: you may see old code examples using input which we changed to input_data to reduce confusion. Both work - but we prefer the less confusing input_data since input was a built in function for Python!


  • requests An easy to use HTTP client - read the documentation here.
  • StoreClient An easy to use database or cache for stashing key & values to maintain state between runs - read the documentation here.
  • print Super helpful if you want to debug your function - you'll need to test your zap to see the values (the logs are returned to you in a runtime_meta added automatically to your output).


Running your zap via the dashboard or the editor is the canonical way to confirm the behavior you expect - your Task History will have all relevant details around the ran code's input_data, output and logs. Step 6 (the test step) in the editor can be used for a tighter feedback loop.

Try asking for by tagging questions as Zapier on Stackoverflow!

Code (Python) Examples#

Important! Every example depends on specific input_data - which is provided under the "Input Data" field when setting up your - this example screenshot shows three demonstration inputs you can use in your code like this: input_data['body'], input_data['name'], and input_data['subject']. Be sure you read the code examples and provide the right inputs otherwise nothing will work as expected!

In this section we provide some examples - it is important to note that Python is an advanced programming language - if you get lost it might make sense to ask a programmer friend or learn python yourself.

Introductory Examples#

Each of the four examples below expects a name in the "Input Data" field.

A easy example might be something as trivial as:

return {'id': 1234, 'hello': 'world!', 'name': input_data['name']}

You can also bind the result to output - the code above has exactly the same behavior as the code below:

output = {'id': 1234, 'hello': 'world!', 'name': input_data['name']}

You'll notice that when it comes to code - you can solve the same problems in hundreds of unique ways!

An example with an early empty return might be something as trivial as:

if input_data['name'] == 'Larry':
    return [] # we don't work for Larry!

return {'id': 1234, 'hello': 'world!', 'name': input_data['name']}

If you return an empty list [], we will not trigger any actions downstream that depend on the code step's output (they will be halted). However, other steps that don't depend on the code step's output will still run unless a filter stops the Zap from going further.

Introductory HTTP Example#

A more complex example (no "Input Data" needed):

response = requests.get('')
response.raise_for_status() # optional but good practice in case the call fails!
return {'id': 1234, 'rawHTML': response.text}

Introductory Logging Example#

This example expects a name in the "Input Data" field:

if input_data.get('name'):
    print('got name!', input_data['name'])

return {'id': 1234, 'hello': 'world!', 'name': input_data['name']}

Test your action and look at the data to see the print result - great for debugging your code!

Simple Math - Divide by Two#

This example expects a rawNumber in the "Input Data" field:

return {
  'calculatedNumber': int(input_data['rawNumber']) / 2

Simple Email Extraction#

This example expects a rawText in the "Input Data" field:

import re
emails = re.findall(r'[\w._-]+@[\w._-]+\.[\w._-]+', input_data['rawText'])
return {
    'firstEmail': emails[0] if emails else None

Complex Multiple Email Extraction#

This example expects a rawText in the "Input Data" field:

import re
emails = re.findall(r'[\w._-]+@[\w._-]+\.[\w._-]+', input_data['rawText'])
return [
    {'email': email} for email in emails

This will trigger multiple downstream actions - one for each email found! If no emails are found - nothing happens.

Formatting a Comma Separated List#

There may be cases where you need to create a comma separated list but you need to eliminate the blank values from the list. This snippet will help you create the list and remove blanks. This example expects a values entry in the "Input Data" field like this:

import re
values = re.sub('(^,+|,+$)', '', input_data['values'])
values = re.sub(',+', ',', values)
return [{'values': values}]

Weather JSON API Call#

This example expects a zipCode in the "Input Data" field:

zc = input_data['zipCode']
url = '' + zc + ',us'
response = requests.get(url)
response.raise_for_status() # optional but good practice in case the call fails!
return response.json()

XML Parsing#

If you need to parse XML and return it, you can do that with the built in XML libraries:

from xml.etree import ElementTree
root = ElementTree.fromstring('''
return [
    {field.tag: field.text for field in child}
    for child in root.findall('child')

If you need to do an API call to parse XML, you can combine this portion with the request examples above:

from xml.etree import ElementTree
response = requests.get('')
root = ElementTree.fromstring(response.text)
return [
    {field.tag: field.text for field in child}
    for child in root.findall('child')

Please note, the part for iterating the data (for child in root.findall('child')) will change depending on whatever the API response looks like, it will not be exactly 'parent' or 'child' like our example above! Experiment with it!

Store State#

It isn't uncommon to want to stash some data away for the next run, our StoreClient can do exactly that. For example - this is a counter that counts how many times it is ran:

store = StoreClient('some secret')

count = store.get('some counter') or 0
count += 1
store.set('some counter', count)
return {'the count': count}

Generate Unique ID (UUID)#

Output a unique identifier using the uuid library:

import uuid

return {
    'unique_id': str(uuid.uuid4())

Only Once Per Hour#

In conjunction with a Filter step, you could use code like this to limit the number of times your zap can run per hour (which is configurable):

every_seconds = 60 * 60

store = StoreClient('some secret')

import time
now = int(time.time())
last_post = store.get('last_post') or now - every_seconds + 1

output = {'run': 'no'}
if last_post < (now - every_seconds):
    output = {'run': 'yes'}
    store.set('last_post', now)

  # don't forget to set up a filter after this that checks if run is exactly yes

Note! Without a follow up Filter step this won't work!

Bulk Lookup Table#

If you have hundreds of values for lookup, you might not want to use the built in lookup table tool! This makes it a lot easier, but you'll want to set up the input values like so:

default = 'some default'

_lookup_table = '''

lookup_table = dict(
    line.split(',', 1)
    for line in _lookup_table.items()
    if ',' in line

return {
    'out_value': lookup_table.get(input_data['in_value'], default)

Now you can use the "Out Value" in later steps!

StoreClient (Python)#

Storing and retrieving data with StoreClient is very simple.

There is no need to import it - it comes pre-imported in your Code environment.

Note that when working with StoreClient, as for all Python Code steps, you will need to return a dictionary or an array of dictionaries. Returning a string will result in an error. See more details here.

You will need to provide a secret that will protect your data. I recommend using's excellent password generator. Be very sure you pick a complex secret - if anyone guesses it they'll be able to read and write your data!

Instantiating a client is very simple:

store = StoreClient('your secret here')

Most likely you just want to get and set some values - this is the simplest possible example:

store = StoreClient('your secret here')
store.set('hello', 'world')
value = store.get('hello') # return 'world'

If the value doesn't exist during your get() call - it will return a None value.

Bulk Operations#

You can also save and retrieve multiple keys and values - a slightly more complex example:

store = StoreClient('your secret here')
store.set_many({'hello': 'world', 'foo': 'bar'})
values = store.get_many('hello', 'foo') # return {'hello': 'world', 'foo': 'bar'}
store.delete_many('hello', 'foo')
store.clear() # or, if you want to wipe everything

Note, you can call get_many and delete_many in a few different ways:

store.get_many('hello', 'foo') # as args
store.get_many(['hello', 'foo']) # as list
store.get_many({'hello': None, 'foo': None}) # as dict

And similarly with set_many:

store.set_many({'hello': 'world', 'foo': 'bar'}) # as dict
store.set_many(hello='world', foo='bar') # as kwargs

Other operations#

Slightly more complex examples include incrementing a numeric value, setting a value if a condition is met or pushing/popping from lists. These operations also have the benefit that they are atomic.

  • increment_by increments a value found under a given key. The value has to be a numeric value in order for this operation to succeed:

    store.increment_by(key, amount)
  • set_value_if sets a value if a condition is met. If the value stored under the given key matches the same value as the given previous value, then the given value parameter will become the new value of the key.

    store.set(key, 1) # set a value
    # sets 2 only if the previous value of *key* is 1
    store.set_value_if(key, value=2, previous_value=1)
  • set_child_values/remove_child_values can be useful for storing/removing nested values. The value under the given key has to be a dictionary.

    store.set_child_values(key, {'a': 'b'}) # store under the given key the key `a` with value `b`
    store.remove_child_values(key, ['a', 'c']) # remove the keys `a` and 'c' from the mapping found at `key`
  • list_pop/list_push can be useful for manipulating lists.

    store.list_push(key, some_value)

    Additionally, list_push and list_pop accept a location parameter.

    store.list_push(key, value, location='tail') # Push to the tail of the list
    store.list_push(key, value, location='tail_set') # Push to the tail of the list only if the value is not already in the list
    store.list_push(key, value, location='head') # Push to the head of the list
    store.list_push(key, value, location='head_set') # Push to the head of the list only if the value is not already in the list
    store.list_pop(key, location='tail') # Pop from the end of the list
    store.list_pop(key, location='head') # Pop from the head of the list

    list_pop can also receive a default parameter, which will be returned when there is nothing to pop from the given list:

    store.list_pop(key, default=1, location='tail')


You can also access the stored data via our store API. More info at


  • Any JSON serializable value can be saved.
  • The secret must be under 32 chars in length.
  • Every key must be under 32 chars in length.
  • Every value must be under 2500 bytes.
  • Only 500 keys may be saved per secret.
  • Keys will expire if you do not touch them in 3 months.

Common Problems with Code (Python) on Zapier#

I need help!#

Try asking for by tagging questions as Zapier on Stack Overflow!

Requiring or Using External Libraries#

Unfortunately you cannot require external libraries or install libraries commonly referred to as "pip modules". Only the standard Python library and requests is available in the Code app and requests is already included in the namespace.

Time & Memory Limits#

Free users are limited to 1 second and 128mb of RAM. Paid users get well over double that at 10 seconds and 256mb of RAM. Your Zap will hit an error if you exceed these limits.

My Floats Get Converted to Integers (or vice versa)!#

If you have a python code step that returns a value like this:

return {'result': 1.0}

it may appear up as 1 (not 1.0) in task history and test results. This is an artifact of the UI. The Zapier web UI does not distinguish between int and float values; they are all just numbers. In your Python code step you can use int(aNumber) or float(aNumber) to make sure to convert the value to the data type you require.

I am getting various SyntaxError's, NameError's or other weird bugs.#

Python is a fairly complex language and you should probably be a programmer or willing to dedicate some serious time to learn to code - while we can't help you fix your code, try asking for by tagging questions as Zapier on Stack Overflow.

Popular Things to Do with Code (Python) on Zapier#

Coming soon!