[metadata]
apple-mobile-web-app-title: Notion Docs
application-name: Notion Docs
description: To ensure a consistent developer experience for all API users, the Notion API is rate limited and basic size limits apply to request parameters.
generator: Mintlify
msapplication-TileColor: #000
msapplication-config: /mintlify-assets/_mintlify/favicons/notion-demo/1PaJq9z3waub4TpE/_generated/favicon/browserconfig.xml
og:description: To ensure a consistent developer experience for all API users, the Notion API is rate limited and basic size limits apply to request parameters.
og:image: https://notion-demo.mintlify.app/images/og-image.png
og:image:height: 630
og:image:width: 1200
og:site_name: Notion Docs
og:title: Request limits - Notion Docs
og:type: website
og:url: https://developers.notion.com/reference/request-limits
twitter:card: summary_large_image
twitter:description: To ensure a consistent developer experience for all API users, the Notion API is rate limited and basic size limits apply to request parameters.
twitter:image: https://notion-demo.mintlify.app/images/og-image.png
twitter:image:height: 630
twitter:image:width: 1200
twitter:title: Request limits - Notion Docs
viewport: width=device-width, initial-scale=1, viewport-fit=cover

[canonical-links]
https://developers.notion.com/reference/request-limits

[document-links]
/llms.txt: /llms.txt
API Reference: /reference/intro
Admin API: /reference/admin/intro
CLI Reference: /cli/get-started/overview
Changelog: /page/changelog
Connection capabilities: /reference/capabilities
Database: /reference/database
Developer portal: https://www.notion.so/developers
Emoji and icon: /reference/emoji-and-icon
Event types & delivery Previous: /reference/webhooks-events-delivery
Examples: /page/examples
Guides: /guides/get-started/overview
Introduction: /reference/intro
Log in: https://www.notion.com/login
Notion Docs home page: /
Parent: /reference/parent-object
Request limits: /reference/request-limits
Retrieve a page property item: /reference/retrieve-a-page-property
Rich text object: /reference/rich-text
Status codes Next: /reference/status-codes
Status codes: /reference/status-codes
Unfurl attribute (Link Previews): /reference/unfurl-attribute-object
User: /reference/user
View: /reference/view
Workers: /workers/get-started/overview
block: /reference/block
rich text objects: /reference/rich-text
slack: https://join.slack.com/t/notiondevs/shared_invite/zt-3u9oid9q8-HLUBmMVWYK~g9HFo4U4raA
x: https://x.com/NotionDevs

[structured-data]
{"@context":"https://schema.org","@graph":[{"@id":"https://developers.notion.com/#organization","@type":"Organization","logo":{"@type":"ImageObject","url":"https://mintcdn.com/notion-demo/5YdhSbldE14t5Rna/logo/light.svg?fit=max&auto=format&n=5YdhSbldE14t5Rna&q=85&s=249f5693ad929397409bf9b51d6d539d"},"name":"Notion Docs","url":"https://developers.notion.com"},{"@id":"https://developers.notion.com#website","@type":"WebSite","name":"Notion Docs","publisher":{"@id":"https://developers.notion.com/#organization"},"url":"https://developers.notion.com"},{"@id":"https://developers.notion.com/reference/request-limits#webpage","@type":"WebPage","breadcrumb":{"@id":"https://developers.notion.com/reference/request-limits#breadcrumb"},"dateModified":"2026-08-04T23:01:36.636Z","description":"To ensure a consistent developer experience for all API users, the Notion API is rate limited and basic size limits apply to request parameters.","isPartOf":{"@id":"https://developers.notion.com#website"},"name":"Request limits","url":"https://developers.notion.com/reference/request-limits"},{"@id":"https://developers.notion.com/reference/request-limits#breadcrumb","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","item":"https://developers.notion.com/reference/intro","name":"Notion API","position":1},{"@type":"ListItem","item":"https://developers.notion.com/reference/request-limits","name":"Request limits","position":2}]},{"@id":"https://developers.notion.com/reference/request-limits#article","@type":["Article","TechArticle"],"dateModified":"2026-08-04T23:01:36.636Z","description":"To ensure a consistent developer experience for all API users, the Notion API is rate limited and basic size limits apply to request parameters.","headline":"Request limits","image":"https://developers.notion.com/images/og-image.png","isPartOf":{"@id":"https://developers.notion.com#website"},"mainEntityOfPage":{"@id":"https://developers.notion.com/reference/request-limits#webpage"},"name":"Request limits","publisher":{"@id":"https://developers.notion.com/#organization"},"url":"https://developers.notion.com/reference/request-limits"}]}

[content]
Request limits - Notion Docs
Documentation Index
Fetch the complete documentation index at:
/llms.txt
Use this file to discover all available pages before exploring further.
Skip to main content
Notion Docs
home page
Search...
⌘
K
Ask Assistant
Log in
Developer portal
Developer portal
Search...
Navigation
Notion API
Request limits
Guides
API Reference
CLI Reference
Workers
Admin API
Changelog
Examples
Notion API
Introduction
Connection capabilities
Webhooks
Request limits
Status codes
Async tasks
Versioning
Objects
Block
Page
Database
Data source
View
Comment
File
User
Parent
Emoji and icon
Unfurl attribute (Link Previews)
Endpoints
Authentication
Blocks
Pages
Databases
Data sources
Databases (deprecated)
Comments
Views
File Uploads
Search
Users
Custom emojis
Webhook events
Pages
Databases
Data sources
Comments
File uploads
Views
On this page
Rate limits
Retry rate-limited requests
Size limits
Limits for property values
Notion API
Request limits
Copy page
Copy page
To ensure a consistent developer experience for all API users, the Notion API is rate limited and basic size limits apply to request parameters.
Copy page
Copy page
​
Rate limits
The Notion API enforces two rate limits:
Per connection
— an average of three requests per second, with some bursts beyond the average allowed.
Per workspace
— shared across all of the workspace’s connections and scaled to the workspace’s plan.
Requests that exceed either limit return a
"rate_limited"
error code and an HTTP 429 response, with
additional_data.rate_limit_reason
indicating which limit was exceeded (for example,
public_api_request_rate_limit
or
public_api_space_request_rate_limit
).
Connections should handle HTTP 429 and 529 responses and respect the
Retry-After
response header. The header value is an integer number of seconds. A 529 response carries the
"service_overload"
code and means Notion is temporarily overloaded; retry it the same way as a 429.
​
Retry rate-limited requests
Put outgoing requests through a queue so a burst from one job does not consume the connection’s full request budget. When Notion returns 429 or 529:
Read
Retry-After
and pause new requests for at least that many seconds.
Retry the failed request after the pause.
If another 429 or 529 arrives, increase the delay with exponential backoff and jitter.
Set a retry limit. Log or surface the final error when the limit is reached.
Do not retry every error. Retry 429 and 529 responses. Retry 500, 502, 503, and 504 responses only when the request is idempotent, such as GET or DELETE, unless your application has its own idempotency protection. Fix the request before retrying most 400 responses. Treat 401 and 403 responses as authentication or authorization failures.
The JavaScript SDK retries 429 responses for every method. It also retries 500 and 503 responses for GET and DELETE requests. It respects
Retry-After
, uses exponential backoff with jitter, and limits retries. If you call the REST API directly, use the same safeguards and add explicit handling for 529 responses. These examples show the same policy in several common HTTP clients:
JavaScript
Python
Go
Java
async
function
notionRequest
(
url
,
options
=
{},
attempt
=
0
) {
const
response
=
await
fetch
(
url
,
options
)
const
method
=
(
options
.
method
??
"GET"
).
toUpperCase
()
const
isIdempotent
=
method
===
"GET"
||
method
===
"DELETE"
const
retryable
=
response
.
status
===
429
||
response
.
status
===
529
||
(
isIdempotent
&&
[
500
,
502
,
503
,
504
].
includes
(
response
.
status
))
if
(
!
retryable
||
attempt
>=
5
) {
return
response
}
const
retryAfter
=
response
.
headers
.
get
(
"retry-after"
)
const
retryAfterSeconds
=
Number
(
retryAfter
)
const
exponentialDelaySeconds
=
Math
.
min
(
2
**
attempt
,
30
)
const
baseDelaySeconds
=
retryAfter
!==
null
&&
Number
.
isFinite
(
retryAfterSeconds
)
?
retryAfterSeconds
:
exponentialDelaySeconds
const
jitterMs
=
Math
.
random
()
*
250
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
baseDelaySeconds
*
1000
+
jitterMs
),
)
return
notionRequest
(
url
,
options
,
attempt
+
1
)
}
import
random
import
time
import
requests
def
notion_request
(
method
,
url
,
*
,
max_attempts
=
6
,
**
kwargs
):
method
=
method.upper()
is_idempotent
=
method
in
{
"GET"
,
"DELETE"
}
for
attempt
in
range
(max_attempts):
response
=
requests.request(method, url,
**
kwargs)
retryable
=
(
response.status_code
in
{
429
,
529
}
or
(
is_idempotent
and
response.status_code
in
{
500
,
502
,
503
,
504
}
)
)
if
not
retryable
or
attempt
==
max_attempts
-
1
:
return
response
retry_after
=
response.headers.get(
"Retry-After"
)
delay
=
float
(retry_after)
if
retry_after
else
min
(
2
**
attempt,
30
)
time.sleep(delay
+
random.uniform(
0
,
0.25
))
func
notionRequest
(
client
*
http
.
Client
,
request
*
http
.
Request
) (
*
http
.
Response
,
error
) {
const
maxAttempts
=
6
isIdempotent
:=
request
.
Method
==
http
.
MethodGet
||
request
.
Method
==
http
.
MethodDelete
for
attempt
:=
0
;
attempt
<
maxAttempts
;
attempt
++
{
attemptRequest
:=
request
.
Clone
(
request
.
Context
())
if
attempt
>
0
&&
request
.
Body
!=
nil
{
if
request
.
GetBody
==
nil
{
return
nil
,
errors
.
New
(
"request body cannot be replayed"
)
}
body
,
err
:=
request
.
GetBody
()
if
err
!=
nil
{
return
nil
,
err
}
attemptRequest
.
Body
=
body
}
response
,
err
:=
client
.
Do
(
attemptRequest
)
if
err
!=
nil
{
return
nil
,
err
}
retryableServerError
:=
response
.
StatusCode
==
500
||
response
.
StatusCode
==
502
||
response
.
StatusCode
==
503
||
response
.
StatusCode
==
504
retryable
:=
response
.
StatusCode
==
429
||
response
.
StatusCode
==
529
||
(
isIdempotent
&&
retryableServerError
)
if
!
retryable
||
attempt
==
maxAttempts
-
1
{
return
response
,
nil
}
response
.
Body
.
Close
()
delay
:=
time
.
Duration
(
1
<<
attempt
)
*
time
.
Second
if
delay
>
30
*
time
.
Second
{
delay
=
30
*
time
.
Second
}
if
seconds
,
err
:=
strconv
.
Atoi
(
response
.
Header
.
Get
(
"Retry-After"
));
err
==
nil
&&
seconds
>=
0
{
delay
=
time
.
Duration
(
seconds
)
*
time
.
Second
}
time
.
Sleep
(
delay
+
time
.
Duration
(
rand
.
Intn
(
250
))
*
time
.
Millisecond
)
}
panic
(
"unreachable"
)
}
HttpResponse
<
String
>
notionRequest
(
HttpClient
client,
HttpRequest
request
) throws IOException, InterruptedException {
int
maxAttempts
=
6
;
boolean
isIdempotent
=
Set
.
of
(
"GET"
,
"DELETE"
).
contains
(
request
.
method
());
for
(
int
attempt
=
0
; attempt
<
maxAttempts; attempt
++
) {
HttpResponse
<
String
>
response
=
client
.
send
(
request,
HttpResponse
.
BodyHandlers
.
ofString
()
);
int
status
=
response
.
statusCode
();
boolean
retryable
=
status
==
429
||
status
==
529
||
(isIdempotent
&&
Set
.
of
(
500
,
502
,
503
,
504
).
contains
(status));
if
(
!
retryable
||
attempt
==
maxAttempts
-
1
) {
return
response;
}
long
retryAfter
=
response
.
headers
().
firstValue
(
"Retry-After"
)
.
map
(Long
::
parseLong)
.
orElse
(
Math
.
min
(
1L
<<
attempt,
30
));
long
jitterMillis
=
ThreadLocalRandom
.
current
().
nextLong
(
250
);
Thread
.
sleep
(retryAfter
*
1000
+
jitterMillis);
}
throw
new
IllegalStateException
(
"unreachable"
);
}
The same rules apply in other languages: centralize retries in the HTTP client, respect
Retry-After
, add jitter, and cap the fallback delay and attempt count. Avoid independent retry loops in each worker; they can create a second traffic spike when the delay expires.
Rate limits may change
In the future, Notion plans to adjust rate limits to balance for demand and reliability.
​
Size limits
Notion limits the size of certain parameters, and the depth of children in requests. A requests that exceeds any of these limits will return
"validation_error"
error code (HTTP response status 400) and contain more specific details in the
"message"
property.
Connections should avoid sending requests beyond these limits proactively. It may be helpful to use test data in your own test suite which intentionally contains large parameters to verify that the errors are handled appropriately. For example, if the connection reads a URL from an external system to put into a Notion page property, the connection should have a plan to deal with URLs that are beyond the length limit of 2000 characters. The connection might choose to log the error, or send an alert to the user who set up the connection via an email, or some other action.
Note that in addition to the property limits below, payloads have a maximum size of 1000 block elements and 500KB overall.
​
Limits for property values
Property value type
Inner property
Size limit
Rich text object
text.content
2000 characters
Rich text object
text.link.url
2000 characters
Rich text object
equation.expression
1000 characters
Any array of all
block
types, including
rich text objects
100 elements
Any URL
2000 characters
Any email
200 characters
Any phone number
200 characters
Any multi-select
100 options
Any relation
100 related pages
Any people
100 users
Request size limits
These cap the size of a single request, not how much a property can hold. A relation property can contain far more than 100 related pages — the limit only governs how many you add or set in one request. Responses have separate limits; use
Retrieve a page property item
to paginate through large values.
Event types & delivery
Previous
Status codes
Next
⌘
I
x
slack
Assistant
Responses are generated using AI and may contain mistakes.
