Yandex Forms API usage examples

This page describes examples of Python scripts that use the Yandex Forms API to manage forms and responses.

All examples use an OAuth token for authentication. To learn how to get a token, see How to get access to the Yandex Forms API.

1. Publishing and unpublishing an existing form

The ability to publish a form via the API is useful when you need to implement complex logic not supported by the default options offered by Yandex Forms, such as scheduling publication at a specific time or unpublishing after reaching a certain number of responses.

See the method descriptions:

Text of the example_1.py script
import os
import requests
import sys

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def publish_survey(survey_id: str) -> bool:
    """
    Publish form.
    The form won't be published if:
    - The form is blocked.
    - The form has reached its response limit.
    - The form has automatic publishing enabled and hasn't reached its scheduled publication time yet.
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/publish'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.post(url, headers=headers)
    return response.status_code == 200


def unpublish_survey(survey_id: str) -> bool:
    """
    You can unpublish any published form, including those that have automatic publishing enabled and haven't reached their scheduled unpublish time yet.
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/unpublish'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.post(url, headers=headers)
    return response.status_code == 200


def main():
    if len(sys.argv) < 2:
        return

    survey_id = sys.argv[1]
    if publish_survey(survey_id):
        print(f'Form {survey_id} published')
    # if unpublish_survey(survey_id):
    #     print(f'Form {survey_id} unpublished')


if __name__ == '__main__':
    main()

Example of running the script:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_1.py 6800cd9202848f10b272a9cc
Form 6800cd9202848f10b272a9cc published

2. Filling out a form using a script

The Yandex Forms API allows forms to be filled out anonymously (by users without an OAuth token), unless the Show form only to authorized users option was explicitly disabled in the form settings.

To submit a form response on behalf of a specific user, make a request using their OAuth token.

A form's field values (answers to questions) are passed in JSON format as question ID-value pairs.

See the Submit form response method description.

Text of the example_2.py script
import json
import os
import requests
import sys

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def submit_survey(survey_id: str, **fields) -> int:
    """

    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/form'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.post(url, json=fields, headers=headers)
    if response.status_code == 200:
        result = response.json()
        return result.get('answer_id')


def main():
    if len(sys.argv) < 3:
        return

    survey_id = sys.argv[1]
    fields = json.loads(sys.argv[2])
    answer_id = submit_survey(survey_id, **fields)
    if answer_id:
        print(f'Form {survey_id} completed. Response {answer_id} created.')


if __name__ == '__main__':
    main()

Example of running the script:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_2.py 6800cd9202848f10b272a9cc '
{
  "id-text": "test it",
  "id-bool": true,
  "id-integer": 42,
  "id-enum": ["id-second", "id-third"]
}
'
Form 6800cd9202848f10b272a9cc completed. Response ‪2037950340‬ created.

3. Retrieving a form response

Let's look at a sample script that fetches a form response by its ID.

See the Получить данные ответа на вопрос method description.

The response data is returned in JSON format. You can process it in Python or using the jq command line utility and convert it to CSV format, if needed.

Text of the example_3.py script
import json
import os
import requests
import sys

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def get_one_answer(answer_id: int):
    """

    """
    url = f'{FORMS_PUBLIC_API}/answers'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    fields = {'answer_id': answer_id}
    response = requests.get(url, fields, headers=headers)
    if response.status_code == 200:
        return response.json()


def main():
    if len(sys.argv) < 2 or not sys.argv[1].isdigit():
        return

    answer_id = int(sys.argv[1])
    answer_data = get_one_answer(answer_id)
    if answer_data:
        survey_id = answer_data['survey']['id']
        print(f'Content of response {answer_id} to form {survey_id} received', file=sys.stderr)
        print(json.dumps(answer_data, indent=2, ensure_ascii=False))


if __name__ == '__main__':
    main()

Example of running the script using the jq utility:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_3.py 2037950340 \
  | jq '.data[] | [.id, .value | if type == "array" then [.[].label] | join(", ") else . end] | @csv'
Content of response ‪2037950340‬ to form 6800cd9202848f10b272a9cc
"\"id-text\",\"test it\""
"\"id-bool\",true"
"\"id-integer\",42"
"\"id-enum\",\"Second, Third\""

4. Exporting form responses using pagination

With the Yandex Forms API, you can retrieve form responses in JSON format with paginated access to results.

See the Получить данные ответа на вопрос method description.

In the example below, the script processes the responses to produce a CSV-compatible output.

Text of the example_4.py script
import csv
import os
import requests
import sys

FORMS_PUBLIC_API_HOST = 'https://api.forms.yandex.net'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def get_value(item):
    value = item.get('value')
    if value is None:
        return ''
    if isinstance(value, list):
        return ', '.join(value)
    return value


def fetch_answers(survey_id: str, *, page_size: int = 50):
    """

    """
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    path = f'/v1/surveys/{survey_id}/answers?page_size={page_size}'
    columns = None
    while True:
        url = f'{FORMS_PUBLIC_API_HOST}{path}'
        response = requests.get(url, headers=headers)
        if response.status_code != 200:
            break

        result = response.json()
        if columns is None:
            columns = result.get('columns') or []
            yield ['ID', 'Created'] + [
                column.get('text')
                for column in columns
            ]

        for answer in result.get('answers') or []:
            yield [answer.get('id'), answer.get('created')] + [
                get_value(item)
                for item in answer.get('data') or []
            ]

        next_page = result.get('next')
        if not next_page:
            break

        path = next_page.get('next_url')
        if not path:
            break


def main():
    if len(sys.argv) < 2:
        return

    survey_id = sys.argv[1]
    print(f'Responses to form {survey_id}', file=sys.stderr)
    csvwriter = csv.writer(sys.stdout, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
    for answer in fetch_answers(survey_id):
        csvwriter.writerow(answer)


if __name__ == '__main__':
    main()

Example of running the script:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_4.py 6800cd9202848f10b272a9cc
Responses to form 6800cd9202848f10b272a9cc
"ID","Created","Short Text","Boolean","Integer","Enumeration"
"‪2037950340‬","2025-04-17T11:30:17Z","test it","True","42","Second, Third"
"‪2037859858‬","2025-04-17T10:14:01Z","test it","True","42","Second"

5. Exporting all answers from a form to a file

To export answers to a file, we'll use several Yandex Forms API calls:

Text of the example_5.py script
import json
import os
import requests
import sys
import time

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def start_export(survey_id: str) -> str:
    """
    Runs a background process to export answers.
    Returns the code of the running operation.
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/answers/export'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    params = {'format': 'xlsx'}
    response = requests.post(url, json=params, headers=headers)
    if response.status_code == 202:
        result = response.json()
        operation_id = result.get('id')
        return operation_id
    print(response.status_code, response.json())


def check_finished(operation_id: str) -> bool:
    url = f'{FORMS_PUBLIC_API}/operations/{operation_id}'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        result = response.json()
        return result.get('status') == 'ok'


def download_result(survey_id: str, operation_id: str) -> bytes:
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/answers/export-results'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    params = {'task_id': operation_id}
    response = requests.get(url, params=params, headers=headers)
    if response.status_code == 200:
        return response.content


def main():
    if len(sys.argv) < 2:
        return

    survey_id = sys.argv[1]
    operation_id = start_export(survey_id)
    if operation_id:
        print(f'Operation {operation_id} launched')

        while not check_finished(operation_id):
            print('...')
            time.sleep(5)

        content = download_result(survey_id, operation_id)
        if content:
            filename = f'{survey_id}.xlsx'
            with open(filename, 'wb') as f:
                f.write(content)

            print(f'Answers exported to {filename}')


if __name__ == '__main__':
    main()

Example of running the script:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_5.py 6800cd9202848f10b272a9cc
Operation 0946779c-6a57-4070-b062-5d7ebdb65142 launched
Answers exported to 6800cd9202848f10b272a9cc.xlsx

6. Uploading and retrieving files

In the example below, the script uploads a file to the form and returns a link that can be used in File fields, as shown in this example: 2. Filling out a form using a script.

See the Upload file to populate form method description.

You can upload a file only if an external file storage is enabled in the form settings: Saving files from responses to the storage.

Text of the example_6.py script
import os
import requests
import sys
from pathlib import Path

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def upload_file(survey_id: str, filename: Path) -> str:
    """
    Upload the file and get a link that we can use when submitting the form
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/files'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    with open(filename, 'rb') as f:
        files = [
            ('file', (filename.name, f.read(), 'application/octet-stream')),
        ]
    response = requests.post(url, files=files, headers=headers)
    if response.status_code == 201:
        result = response.json()
        return result.get('path')


def download_file(filepath: str) -> bytes:
    """
    Download the uploaded file
    """
    url = f'{FORMS_PUBLIC_API}/files'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    params = {'path': filepath}
    response = requests.get(url, params=params, headers=headers)
    if response.status_code == 200:
        return response.content


def main():
    if len(sys.argv) < 3:
        return

    survey_id = sys.argv[1]
    filename = Path(sys.argv[2])
    uploaded_path = upload_file(survey_id, filename.expanduser())
    print(f'Path to the uploaded file: {uploaded_path}')

    content = download_file(uploaded_path)
    print(content)


if __name__ == '__main__':
    main()

Example of running the script:

$ echo 'Hello world' > hello.txt

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_6.py 6800cd9202848f10b272a9cc hello.txt
Path to the uploaded file: /25871573/6800cd9202848f10b272a9cc/68061a8e381ea60011e104b3_hello.txt
b'Hello world\n'