Skip to main content

Instapaper API Python Library

The official Python client for the Instapaper API v2. Save articles, keep a user's library in sync, organize bookmarks into folders and tags, work with highlights, and read parsed article text.

It has no dependencies outside the Python standard library.

Installation

pip install instapaper-api

Requires Python 3.10 or later.

Quick start

If you're calling the API for your own Instapaper account, such as from a script or a personal tool, you don't need the OAuth flow. Register an application, then generate an access token on its page. See Accessing your own account.

from instapaper import Instapaper

client = Instapaper("your-access-token")

for bookmark in client.bookmarks.list():
    print(bookmark.title, bookmark.url)

bookmark = client.bookmarks.save("https://example.com/article", title="An Article")
client.bookmarks.like(bookmark.id)

Authenticating other users with OAuth

To act on behalf of other Instapaper users, send them through the OAuth 2 authorization code flow. Add your redirect URI to your application's callback URIs first; it has to match exactly.

import secrets

from instapaper import Instapaper, OAuth

oauth = OAuth(
    client_id="your-client-id",
    client_secret="your-client-secret",
    redirect_uri="https://yourapp.example.com/callback",
)

state = secrets.token_urlsafe(16)
url = oauth.authorization_url(state=state)
# Redirect the user to `url`. Instapaper sends them back to your redirect URI
# with ?code=...&state=... once they approve.

# In your callback, check that `state` matches, then:
token = oauth.exchange_code(code)
client = Instapaper(token.access_token)

Access tokens don't expire, so store the token rather than the code. Keep your client secret on your server.

Bookmarks

# One page of a section: home (default), archive, liked, folder, or tag
page = client.bookmarks.list(section="archive", limit=50)
print(f"{len(page)} of {page.total}")
for bookmark in page:
    print(bookmark.title)

# Every bookmark in a folder, fetched page by page
for bookmark in client.bookmarks.iterate(folder_id=99):
    ...

# Save with tags, straight into a folder
client.bookmarks.save("https://example.com/recipe", tags=["Recipes"], folder_id=99)

# Save content that has no public URL
client.bookmarks.save(private_source="Acme Reader", content="<p>...</p>", title="A Private Article")

client.bookmarks.update(12345, progress=0.42)
client.bookmarks.archive(12345)
client.bookmarks.move_to_folder(12345, 99)
client.bookmarks.update_tags(12345, add=["Recipes"], remove=[7])
client.bookmarks.delete(12345)  # permanent, not the same as archiving

Syncing

sync returns everything that changed since a Unix timestamp, across every section, including the IDs of bookmarks deleted since then.

import time

started = int(time.time())
changes = client.bookmarks.sync(since=last_sync)
for bookmark in changes.bookmarks:
    ...  # insert or update your local copy
for bookmark_id in changes.deleted_ids:
    ...  # remove it locally
last_sync = started

Use changes instead if you want to fetch one page at a time.

Article text

article = client.bookmarks.parse(12345)
print(article.metadata.title)
print(article.content.body)  # HTML with scripts stripped

Parsing without a key is allowed for personal use, when the account you're reading belongs to the developer who registered the application. To read other users' articles, pass your own Instaparser key as instaparser_api_key. See Non-personal use, and read the API Terms of Use for what you may do with article text.

Folders, tags, and highlights

folder = client.folders.create("Recipes")
client.folders.reorder({folder.id: 1})
client.folders.delete(folder.id)  # its bookmarks move back to the home list

tag = client.tags.create("Cooking")
client.tags.rename(tag.id, "Food")

highlight = client.highlights.create(12345, "The passage the reader marked.")
client.highlights.list(12345)
client.highlights.delete(highlight.id)

Accounts without Instapaper Premium can create five highlights a month. Past that, create raises PermissionDeniedError.

Errors

Every error this library raises is an InstapaperError. When the API answers with an error status you get an APIError subclass carrying status and message:

Exception Status When
BadRequestError 400 A missing or invalid argument
AuthenticationError 401 The access token is missing, unknown, or revoked
QuotaExceededError 402 Instaparser credits ran out
PermissionDeniedError 403 The application isn't approved or is suspended, or a Premium limit
NotFoundError 404 No such endpoint
RateLimitError 429 Too many requests
ServerError 5xx Something went wrong on Instapaper's side

InstapaperConnectionError means the request never got a response, and OAuthError comes from OAuth.exchange_code.

from instapaper import AuthenticationError, RateLimitError

try:
    client.bookmarks.save("https://example.com/article")
except AuthenticationError:
    ...  # ask the user to reconnect
except RateLimitError:
    ...  # back off and try again later

Branch on the exception type or status, not on message, which may be reworded over time.

Documentation

The full API reference lives at instapaper.com/developers.

License

MIT. See LICENSE.

Release files for instapaper-api 1.0.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 instapaper-api 1.0.0
File Size Uploaded
instapaper_api-1.0.0.tar.gz 15.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for instapaper-api 1.0.0
File Interpreter ABI Platform
instapaper_api-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.3 kB

Release files / instapaper_api-1.0.0.tar.gz

Download URL instapaper_api-1.0.0.tar.gz
Size 15.4 kB
Tags Source
SHA-256 checksum
How to use checksums
34103b4684f64594eecfae44600079cf72e27bde5605a46ada660013f8915297
BLAKE2b-256 checksum
How to use checksums
73000e3f52eb61d5541ee31ea23eaa420ee18479d1f936532391953ec4b813ab
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 Sep 29, 2026.

Transparency log

Release files / instapaper_api-1.0.0-py3-none-any.whl

Download URL instapaper_api-1.0.0-py3-none-any.whl
Size 18.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9a4a5d655e32773186581fe53dbff1dc29911f322ef2bd1843f3e02169174fa0
BLAKE2b-256 checksum
How to use checksums
75f28e35bcd7e7be59c04849f4b339e2d2dcdcbc13bdb17dc9a7d966b44b343c
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 Sep 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

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