Full Developer API

The Instapaper API allows third-party applications to add URLs to Instapaper. If you only need to add URLs from your application to an Instapaper customer's account, consider using the Simple API.

Use of the API constitutes agreement to the API Terms of Use. Please read it, really. It's short and contains important implementation rules.

If you find a bug, or a minor change in the API could make your life a lot easier, please send feedback.


This API has been designed for ease of implementation. All methods and requirements are intentionally kept very simple, with one exception: almost all functionality requires OAuth.


Instapaper's API uses OAuth 1.0a implementation, which requires signatures on requests. We recommend using an OAuth 1.0a library to help with signing the request.

xAuth is the only way to get an Instapaper access token.

Other details:

  • Only the HMAC-SHA1 signature method is supported.
  • HTTPS is required on all endpoints. HTTP support is deprecated as of April 1st 2014, and will not be supported as of June 1st 2014. If you are currently using HTTP requests, please take the necessary steps to enable HTTPS on all API requests prior to June 1st.
  • All requests should be made via the POST method, and all parameters should be passed in the POST request-body and not in the query-string.
  • The OAuth parameters should be passed in the Authorization: header, not in the query-string or request-body.
  • Account usernames may change. When storing a reference to accounts, you should store the numeric user_id when possible, and only use the username for display purposes. On methods that return a copy of the user object for the current account, such as bookmarks/list, check the username value to see if it has changed and record the change in your application as necessary.
Get a token for your application

To get an OAuth consumer token for your application, fill this out.

All token requests are reviewed by a human before being activated.

Output formats

Instapaper strings are always encoded in UTF-8, and Instapaper expects all input to be in UTF-8.

Unless otherwise noted, output from every method is an array. The output array is returned as JSON by default.

  • You can specify a jsonp parameter with a callback function name, e.g. jsonp=myCallback, to use JSONP and wrap the output in a call to the specified function.

Each item in the array is an associative array (a hash) containing simple named parameters, each with a type key to describe it. Possible type values:

  • user: An Instapaper user account.
  • bookmark: A saved article.
  • folder: A folder.
  • error: An error.
  • meta: Response metadata, where available.

Example output:

        "title":"Example page 1",
        "description":"An example page."
        "title":"Example page 2",
        "description":"Another example page."
        "text":"example page",

Errors are returned in the same way whenever possible, e.g.:

[{"type":"error", "error_code":1240, "message":"Invalid URL specified"}]

The message value in errors is meant to assist programmers during development and debugging, and is not intended to be displayed to users.

If the response is not valid JSON, it should be interpreted as an HTTP 503 "Service Temporarily Unavailable" error, and the request should be retried later.

The qline format

qline support is deprecated as of version 1.1 of the API. Please use JSON for all endpoints.

A simple custom format called qline is also supported for environments without convenient JSON decoding, but with a URL-decode string function. (If anyone ever asks, the way to pronounce it is "Queue-Line", because it's short for Query-String Line.)

Append the optional parameter format=qline in the API call to get qline output.

This format encodes Instapaper's array items as lines, separated by a standard \n newline character, with each line being encoded like a URL query-string. For example:


Errors work the same way:


These can be quickly decoded with this pseudocode algorithm:

objects = {}
for each line in input.split("\n"):
    attributes = {}
    for each pair in line.split("&"):
        parts = pair.split("=");
        attributes[parts[0]] = url_decode(parts[1]);

    if (attributes[type] is set) objects.append(attributes)

return objects

Empty lines should be ignored. If the response is not parseable, or has no recognizable objects with known type values, it should be interpreted as an HTTP 503 "Service Temporarily Unavailable" error, and the request should be retried later.

Account methods

Gets an OAuth access token for a user.

Input parameters:

  • x_auth_username: The user's username.
  • x_auth_password: The user's password, if the account has one.
  • x_auth_mode: Must be the value "client_auth".

Output on success: A single-line qline-like output (not JSON, to match conventions when issuing access tokens) with the OAuth access token and secret to use, e.g.:


Generated tokens and secrets are currently each up to 50 characters long. They are case-sensitive and may contain letters and numbers, but will not contain other symbols.


Returns the currently logged in user.

Output on success: A user object, e.g.

Bookmark methods

Lists the user's unread bookmarks, and can also synchronize reading positions.

Input parameters:

  • limit: Optional. A number between 1 and 500, default 25.
  • folder_id: Optional. Possible values are unread (default), starred, archive, or a folder_id value from /api/1.1/folders/list.
  • have: Optional. A concatenation of bookmark_id values that the client already has from the specified folder. See below.
  • highlights: Optional. A '-' delimited list of highlight IDs that the client already has from the specified bookmarks.

Output: A JSON object, not the standard API output structures, with format:

    "user":{<user object>},
    "bookmarks":[{<bookmark 1>}, ... ],
    "highlights":[{<highlight 1>}, ... ],
    "delete_ids":[<list of deleted bookmark IDs>]

Warning: HTML in highlight text is returned unescaped through the API.

The "have" parameter:

This is a comma-separated list of bookmark_id values that the client already has in its local bookmark data, and shouldn't be re-sent. Any IDs sent in the have parameter that would not have appeared in the list within the given limit are returned in a delete_ids parameter on the meta object.

The have parameter can just be a list of the bookmark_id values, e.g.:


...in which case Instapaper won't include those bookmarks in the output.

But it can also do more. Each bookmark returned by the API has a hash value, which is computed from its URL, title, description, and reading progress. If you join the hash value you have for an article with its article ID using a colon, e.g.:


...then Instapaper will omit those bookmarks from the output, but only if the hashes haven't changed. So you can use this method to selectively be informed of updates to article metadata without otherwise re-downloading the entire list on each update.

Finally, you can optionally append two more fields to each ID with colons to indicate how far the user has read each article, as a floating-point value between 0.0 and 1.0 to indicate progress and the Unix timestamp value of the time that the progress was recorded, e.g.:


This would indicate that the bookmark with bookmark_id=12345 and hash=OjMuzFp6 was read to 0.5 progress, or 50% of its length, at timestamp 1288584076 (2010-11-01 12:01:16am EST). If the server's information is less recent than this, it will update the bookmark and return it in the output with a new hash value.


Updates the user's reading progress on a single article. This functionality is included in the have parameter of the /api/1.1/bookmarks/list operation above, but this method exists in case you want to call it separately.

Input parameters:

  • bookmark_id: The bookmark to update.
  • progress: The user's progress, as a floating-point number between 0.0 and 1.0, defined as the top edge of the user's current viewport, expressed as a percentage of the article's total length.
  • progress_timestamp: The Unix timestamp value of the time that the progress was recorded.

Output: The modified bookmark on success.


Adds a new unread bookmark to the user's account.

Input parameters:

  • url: Required, except when using private sources (see below).
  • title: Optional. If omitted or empty, the title will be looked up by Instapaper synchronously. This will delay the action, so please specify the title if you have it.
  • description: Optional. A brief, plaintext description or summary of the article. Twitter clients often put the source tweet's text here, and Instapaper's bookmarklet puts the selected text here if the user has selected any.
  • folder_id: Optional. The integer folder ID as returned by the folders/list method described below.
  • resolve_final_url: Optional, default 1. Specify 1 if the url might not be the final URL that a browser would resolve when fetching it, such as if it's a shortened URL, it's a URL from an RSS feed that might be proxied, or it's likely to go through any other redirection when viewed in a browser. This will cause Instapaper to attempt to resolve all redirects itself, synchronously. This will delay the action, so please specify 0 for this parameter if you're reasonably confident that this URL won't be redirected, such as if it's already being viewed in a web browser.

Output: The bookmark on success, which may not be new: if this user already saved this URL, it will be moved to the top of the Unread list (or the specified folder) and assigned the new values for title, description, and content (see below).

In addition to standard invalid-parameter errors, you may encounter these special errors:

  • 1220: Domain requires full content to be supplied -- Pages from this domain require the content parameter below, usually because a login or Instapaper Premium is required to get their content, and you haven't supplied it. If you already have the page loaded in a browser environment, simply re-submit with the body contents (e.g. Javascript's document.body.innerHTML). If not, you may need to open it in a browser first, or give the user a helpful message explaining that content from this site needs to be viewed in a browser before saving to Instapaper.
  • 1221: Domain has opted out of Instapaper compatibility -- The publisher of this domain has requested that Instapaper not save any of its content. Do not attempt to work around this, which is prohibited in the API Terms of Use. Please give the user a helpful message, where applicable, that the publishers of this site do not permit Instapaper usage.
Supplying HTML content for a bookmark

You can optionally supply the full HTML content of pages that Instapaper wouldn't otherwise be able to crawl from its servers, such as pages that require logins or Instapaper Premium.

  • content: The full HTML content of the page, or just the <body> node's content if possible, such as the value of document.body.innerHTML in Javascript. Must be UTF-8.

A bookmark's content is not shared to other users through any sharing functionality (such as Starred-folder subscriptions). It is only used to generate the text version of the bookmark for the user that created it.

This is not for material that doesn't have a dedicated, permanent URL or should be excluded from sharing and tracking functionality completely, such as a private message on a social network, driving directions, or the results of a session. For that, see "Private sources" below.

Private sources

Bookmarks can be private, such as the bookmarks that result from Instapaper's email-in text feature. Private bookmarks are not shared to other users through any sharing functionality (such as Starred-folder subscriptions), and they do not have URLs.

Set this parameter to a non-empty string to set a bookmark to private:

  • is_private_from_source: A short description label of the source of the private bookmark, such as "email" or "MyNotebook Pro".

When using this, values passed to url will be ignored, and the content parameter (above) is required.

In any bookmark objects output by this API, the private_source field will be an empty string for public bookmarks, and this value for private bookmarks. They will have an automatically generated, non-functioning value in the url field of the form instapaper://private-content/.... Do not use these URLs in your application.


Permanently deletes the specified bookmark. This is NOT the same as Archive. Please be clear to users if you're going to do this.

Input parameter: bookmark_id

Output: An empty array on success.


Stars the specified bookmark.

Input parameter: bookmark_id

Output: The modified bookmark on success.


Un-stars the specified bookmark.

Input parameter: bookmark_id

Output: The modified bookmark on success.


Moves the specified bookmark to the Archive.

Input parameter: bookmark_id

Output: The modified bookmark on success.


Moves the specified bookmark to the top of the Unread folder.

Input parameter: bookmark_id

Output: The modified bookmark on success.


Moves the specified bookmark to a user-created folder.

Input parameters: bookmark_id, folder_id

Output: The modified bookmark on success.


Returns the specified bookmark's processed text-view HTML, which is always text/html encoded as UTF-8.

Input parameters: bookmark_id

Output: HTML with an HTTP 200 OK status, not the standard API output structures, or an HTTP 400 status code and a standard error structure if anything goes wrong.

Folder methods

Input parameters: None.

Output: A list of the account's user-created folders. This only includes organizational folders and does not include RSS-feed folders or starred-subscription folders, as the implementation of those is changing in the near future.


Creates an organizational folder.

Input parameters: title

Output: The newly created folder, or error 1250: "User already has a folder with this title" if the title isn't unique among this user's folders.


Deletes the folder and moves any articles in it to the Archive.

Input parameter: folder_id

Output: An empty array on success.


Re-orders a user's folders.

Input parameter: order, a set of folder_id:position pairs joined by commas, where the position is a positive integer 32 bits or less. Example input, given the folder_ids 100, 200, and 300, wanting to order them in that order:


Or, to reverse their order:


The order of the pairs doesn't matter, only the position values do, so this is equivalent to the above value:


You must include all of the user's folders for consistent ordering. Invalid or missing folder IDs or positions will be ignored and will not return errors.

Output: The user's re-ordered folder list.

Highlight methods


List highlights for <bookmark-id>

Warning: HTML in highlight text is returned unescaped through the API.

Input parameters: None.

Output: An array of highlights for <bookmark-id>


Create a new highlight for <bookmark-id>

HTML tags in text parameter should be unescaped.

Note: Non-subscribers are limited to 5 highlights per month.

Input parameters:

  • text: The text for the highlight
  • position: Optional. The 0-indexed position of text in the content. Defaults to 0.

Output: The created highlight


Delete a highlight

Input parameters: None.

Output: None.


These are the most common errors you may receive.

General errors:

  • 1040: Rate-limit exceeded
  • 1041: Premium account required
  • 1042: Application is suspended

Bookmark errors:

  • 1220: Domain requires full content to be supplied
  • 1221: Domain has opted out of Instapaper compatibility
  • 1240: Invalid URL specified
  • 1241: Invalid or missing bookmark_id
  • 1242: Invalid or missing folder_id
  • 1243: Invalid or missing progress
  • 1244: Invalid or missing progress_timestamp
  • 1245: Private bookmarks require supplied content
  • 1250: Unexpected error when saving bookmark

Folder errors:

  • 1250: Invalid or missing title
  • 1251: User already has a folder with this title
  • 1252: Cannot add bookmarks to this folder

Operational errors:

  • 1500: Unexpected service error
  • 1550: Error generating text version of this URL

Highlight Errors:

  • 1600: Cannot create highlight with empty text
  • 1601: Duplicate highlight
About Instapaper credentials

Every user has a unique username, which is almost always an email address. Passwords are not required, though most users do use one. Any interface prompting the user for credentials must accommodate this -- for example, you cannot assume that an empty password is a user error.

Authentication behavior:

  • If an account has a password and an incorrect one is supplied, authentication fails.
  • If an account does not have a password, any value works.
Preferred language

Wherever possible, please conform to the interface standards of your environment.

When prompting for the username, please label the field "Email or username", "Email address or username", or "Username".

If possible, when prompting for an Instapaper password, clarify that it is only required if they actually have a password. For example, on the website's login form, the box is labeled "Password, if you have one."

Suggested button or menu titles for the save-URL action: "Send to Instapaper", "Save to Instapaper", "Instapaper". Please avoid adding "you" or "me", e.g. "your Instapaper account", "my Instapaper", etc. in this context. (But that's fine when prompting for credentials.)

↑   Click & drag up to your Bookmarks Bar.