Skip to main content

ExportComments API for Python

This is the official Python client for the ExportComments API v3. Export comments and reviews from 40+ social media and review platforms including Instagram, YouTube, TikTok, Facebook, Twitter/X, Reddit, Trustpilot, Amazon, and more.

Installation

pip install exportcomments

Or install from source:

git clone https://github.com/exportcomments/exportcomments-python.git
cd exportcomments-python
pip install -r requirements.txt
python setup.py install

Usage

Initialize the client with your API token (get it at app.exportcomments.com/user/api):

from exportcomments import ExportComments

ex = ExportComments('<YOUR API TOKEN HERE>')

Check API Connectivity

result = ex.ping()
print(result)  # {'message': 'pong'}

Create an Export Job

Start an export by submitting a URL. The queue is limited to 5 concurrent requests.

response = ex.jobs.create(
    url='https://www.instagram.com/p/1234567',
    options={'replies': True, 'limit': 100}
)
guid = response.body['guid']

Check Job Status

response = ex.jobs.check(guid=guid)
status = response.body['status']  # 'queueing', 'progress', 'done', or 'error'

# Or block until the job is finished (polls every 10s, 1h timeout by default)
job = ex.jobs.wait(guid)

Bulk Export (many URLs in one call)

Premium and Business plans can submit a list of URLs at once. The server queues them and runs them at your plan's concurrency; every URL becomes a regular job.

response = ex.jobs.create_batch(
    urls=[
        'https://www.instagram.com/p/AAAAAAA/',
        'https://www.instagram.com/p/BBBBBBB/',
    ],
    options={'replies': True},
)
batch_id = response.body['batchId']
guids = response.body['guids']        # one per accepted URL
rejected = response.body['errors']    # URLs the server did not accept

status = ex.jobs.wait_batch(batch_id)   # or ex.jobs.check_batch(batch_id).body
for job in status['exports']:
    print(job['url'], job['status'], job['total'])

Limits: Business tokens may hold up to 100 queued URLs and send 5 batch submissions per 10 minutes (Premium: 25 queued, 5 per 30 minutes). Only accepted submissions count toward the window.

Exports with 0 results

When the source returns nothing for a URL (private or login-gated content, comments disabled, filters too narrow), the job finishes as done with total: 0. No file is produced in that case — download_url / json_url are null and result_note explains why. download() and download_json() raise EmptyExportError instead of failing on a dead link:

from exportcomments.exceptions import EmptyExportError

try:
    ex.jobs.download(guid)
except EmptyExportError as e:
    print(e.result_note)

For login-gated content, run the export with your own session cookies (Advanced Mode, see Job Options below).

List Jobs

response = ex.jobs.list(page=1, limit=10)
jobs = response.body

Download Export File

Download the Excel/CSV file for a completed job:

# Downloads and saves the file, returns the file path
file_path = ex.jobs.download(guid=guid)
print(f"Saved to: {file_path}")

# Or specify a custom output path
file_path = ex.jobs.download(guid=guid, output_path='my_export.xlsx')

Download Raw JSON Data

Get the exported data as parsed JSON:

data = ex.jobs.download_json(guid=guid)
for comment in data:
    print(comment['message'], comment['author_name'])

Job Options

The API supports various options when creating a job:

response = ex.jobs.create(
    url='https://www.instagram.com/p/1234567',
    options={
        'replies': True,
        'limit': 500,
        'minTimestamp': 1622505600,
        'maxTimestamp': 1625097600,
        'vpn': 'Norway',
        'cookies': {
            'sessionid': 'your_session_id'
        }
    }
)

Backward Compatibility

For backward compatibility, ex.exports still works as an alias for ex.jobs:

response = ex.exports.create(
    url='https://www.instagram.com/p/1234567',
    options={'replies': True}
)

Handling Errors

from exportcomments.exceptions import ExportCommentsException

try:
    response = ex.jobs.create(
        url='https://www.instagram.com/p/1234567',
        options={'replies': True}
    )
except ExportCommentsException as e:
    print(e)
Exception Class Description
ExportCommentsException Base class for all exceptions.
RequestParamsError Invalid parameter sent. Check the message or response object for details.
AuthenticationError Authentication failed, typically due to an invalid API token.
ForbiddenError Insufficient permissions for the requested action.
PlanRateLimitError Too many requests per minute according to your plan's limits.
ConcurrencyRateLimitError Too many requests per second.
EmptyExportError The job finished with 0 results, so there is no file to download (result_note says why).

Complete Example

from exportcomments import ExportComments
from exportcomments.exceptions import ExportCommentsException
import time
import sys

ex = ExportComments('<YOUR API TOKEN HERE>')

# Verify connectivity
print(ex.ping())

# Create export
try:
    response = ex.jobs.create(
        url='https://www.instagram.com/p/1234567',
        options={'replies': True, 'limit': 100}
    )
except ExportCommentsException as e:
    print(e)
    sys.exit()

guid = response.body['guid']

# Poll until done
while True:
    response = ex.jobs.check(guid=guid)
    status = response.body['status']

    if status == 'done':
        break
    elif status == 'error':
        print("Error:", response.body.get('error'))
        sys.exit()

    time.sleep(5)

# Download the file
file_path = ex.jobs.download(guid=guid)
print(f"Downloaded: {file_path}")

# Or get raw JSON data
data = ex.jobs.download_json(guid=guid)
print(f"Got {len(data)} comments")

Changelog

2.2.0

  • Bulk exports: create_batch(), check_batch(), wait_batch() (POST /api/v1/batch-export)
  • wait(guid) polls a job until it is finished
  • EmptyExportError for jobs that finished with 0 results (no file exists); reads the API's result_note
  • Error messages surface the API's error text instead of a generic "Internal server error"

API v3 Changes

Version 2.0.0 supports API v3:

  • New method names: Use ex.jobs instead of ex.exports (backward compatibility maintained)
  • Updated parameters: create() uses an options dict instead of individual parameters
  • New methods: ping(), download(), download_json()
  • Endpoints: Uses /api/v3/ endpoints

For more information, visit ExportComments API Documentation.

Metadata

Release files for exportcomments 2.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for exportcomments 2.2.0
File Size Uploaded
exportcomments-2.2.0.tar.gz 12.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for exportcomments 2.2.0
File Interpreter ABI Platform
exportcomments-2.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.0 kB

Release files / exportcomments-2.2.0.tar.gz

Download URL exportcomments-2.2.0.tar.gz
Size 12.2 kB
Tags Source
SHA-256 checksum
How to use checksums
70eaa6faaffe565e8e180387335f5a0ee608b69f570a183b21d3d0ee4f18f77c
BLAKE2b-256 checksum
How to use checksums
ba9c8462f814de51cbd25f6a346e29112dbedc293ca16ada153f8fe62f6568ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / exportcomments-2.2.0-py3-none-any.whl

Download URL exportcomments-2.2.0-py3-none-any.whl
Size 11.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
73acf4cf91c40c0b04b125f6f296ec9215692fa0e379f42246d84ced686e8818
BLAKE2b-256 checksum
How to use checksums
776c66e08372338ce28942c07dc8e50cf07d5aae9c991c59069e487faf89f45a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.2.0 This release

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.0.1

1 release file

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page