The Notion to HTML API will convert your (private) database items to HTML. You can customise the HTML output with multiple query parameters. If you want to convert a public Notion page to HTML. Use this API by @asnunes.
- Create a Notion integration at notion.so/my-integrations and provide access to the databases you want to use.
- To authorize each request, add a
token
parameter in the request body and set the value to theInternal Integration Token
of your Notion integration - Get the HTML of any page at
https://notion-to-html.herokuapp.com/[pageId]
.
How to get the pageId? Get it with an integration or see how get it manually (go to "Where can I find my page's ID?").
- Clone this repository
- Run
npm install
to install dependencies - Run
npm run start
to start the development server onlocalhost:3000
For production deployment I recommend Heroku
The API uses standard HTTP error codes.
200 - OK
: Everything worked out as expected401 - Unauthorized
: No valid API key provided.500 - Server error
: Something unexpected happened, the API is down
Nested child blocks are supported only one level depp on toggle, list and to_do blocks.
- First level list
- Second level list
- Third level list (unsupported)
> Second level toggle
> Third level paragraph (unsupported)
- paragraph
- heading_1
- heading_2
- heading_3
- bulleted_list_item
- numbered_list_item: by default rendered as a bullet list, see improved lists parameter for a workaround)
- to_do
- toggle
- child_page
- image
- divider
- quote
- code
- file
- callout
- video
- bookmark
- table_of_contents
- breadcrumb
- embed
- link_preview
- synced_block
- table
- table_row
- child_database
- Inline styles are used for setting text color, backgrounds, annotations.
callout
blocks are automatically styled with a background color or a border- Add optional parameters for improved styling.
Each param expects a boolean value and is set to false
by default. To apply a parameter add it to the request query: notion-to-html.herokuapp.com/pageId?param1=true¶m2=true
Key | When set to true |
---|---|
webflow |
Optimizes styling for Webflow Richtext |
uploadImages |
Uploads each uploaded image to Cloudinary |
headingIds |
Adds ids on headings for in-page links |
headingAnchors |
Adds anchor links before each heading |
darkMode |
Optimizes the color scheme for dark mode |
htmlTags |
Converts annotations as HTML tags (instead of styles) |
copyCodeBtn |
Inserts a button for copying code blocks |
webflow
param adds classes to optimize the output for Webflow Rich Text block. See my blog post for copy-paste custom Webflow styles.
Image tweaks:
- Lazy loading
- Class
w-richtext-figure-type-image
- Class
w-richtext-figure-type-fullwidth
(for images without captioncenter
) - Images with
center
keyword in caption will set the image to centered with the classnamew-richtext-align-center
.
Other improved elements:
- second level
<ul>
(classul-2nd-level
) - code (class
pre-container
) - dividers (class
divider
) - videos (classes
w-richtext-align-fullwidth w-richtext-figure-type-video
, default iframe styling)
Toggles are changed to:
<details>
<summary class="toggle-summary">
<div className="toggle-triangle">
<span>▶</span>
</div>
<div className="toggle-summary-content">Toggle summary</div>
</summary>
<div className="details-content">Hidden toggle content</div>
</details>
URLs of images uploaded to Notion expire after one day. This is why each image must pe uploaded to a third party. Note: duplicate uploads are prevented.
Image upload setup:
- Create a http://cloudinary.com/ account
- Click
Start configuring
underConfigure your SDK
- Get the Cloud name, Api key and Api secret, and define following keys in the request body:
cloudinaryCloudName
,cloudinaryApiKey
,cloudinaryApiSecret
and set the right values. - Set the
uploadImages
parameter to true
Adds id
to all heading blocks. With this param turned on, you can use native Notion in-document anchors. Use the link in the form your-page.com/article-slug#heading-id
.
Adds an anchor icon before each heading block. This parameter works only id headingIds
is turned on as well.
The anchor element will have the following form:
<h1>
<a href="#heading-id" class="heading-anchor">
<svg><!-- Anchor icon --></svg>
</a>
<span>Example heading</span>
</h2>
Recommended anchor icon styling:
.heading-anchor {
padding-right: 4px;
margin-left: -20px;
visibility: hidden;
line-height: 1;
border: none !important;
}
h1:hover .heading-anchor,
h2:hover .heading-anchor,
h3:hover .heading-anchor {
visibility: visible;
}
Optimizes the background and text colors for dark mode.
Converts inline styles to corresponding HTML tags.
For example <span style="font-weight:bold">text</span>
changes to converted to <strong>text</strong>
.
Annotation | HTML tag |
---|---|
bold | <strong> |
italic | <i> |
strikethrough | <strike> |
inline co de | <code> |
underline | <u> |
Inserts a button compatible with the FinSweets' Copy to clipboard attribute in each code block. If turned on, the following structure is given to code blocks:
<pre>
<code>{CODE CONTENT}</code>
<a href="#" className="copy-button"
fs-copyclip-element="click"
fs-copyclip-text="{CODE CONTENT}"
fs-copyclip-message="Copied!"
fs-copyclip-duration="1000"
>Copy</a>
</pre>