This workflow corresponds to n8n.io template #4800 β we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide β
{
"id": "CtgqZVTypq95HoSi",
"name": "Save Mastodon Bookmarks to Raindrop Automatically",
"tags": [],
"nodes": [
{
"id": "4e0a9ee0-5cd6-4d27-8cc1-e9171f9d8bd1",
"name": "Allows manual testing of the workflow",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1540,
100
],
"parameters": {},
"typeVersion": 1
},
{
"id": "f191c5e3-adf2-4e00-9ef2-76872dde02c6",
"name": "Triggers the workflow on a set interval",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1540,
300
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "6f2bc516-7496-418e-bc71-2c83b4d2b9d5",
"name": "Retrieves the last processed min_id to avoid duplicates",
"type": "n8n-nodes-base.code",
"position": [
-1320,
200
],
"parameters": {
"jsCode": "// initialize staticData object\nconst workflowStaticData = $getWorkflowStaticData('global');\n\n// initialize accessToken on staticData if it desn't exist yet\nif (!workflowStaticData.hasOwnProperty('min_id')) {\n workflowStaticData.min_id = 0\n}\n\n\n\nreturn [\n {\n // data: $input.all(),\n min_id: workflowStaticData.min_id,\n // today: $today\n }\n];"
},
"typeVersion": 2
},
{
"id": "a119babd-8305-4476-8a84-5285e1890dd8",
"name": "Makes authenticated request to Mastodon\u2019s bookmarks API",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1100,
200
],
"parameters": {
"url": "{VOTRE SERVEUR MASTODON}/api/v1/bookmarks",
"options": {
"response": {
"response": {
"fullResponse": true
}
},
"lowercaseHeaders": true
},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"queryParameters": {
"parameters": [
{
"name": "min_id",
"value": "={{ $json.min_id }}"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"alwaysOutputData": true
},
{
"id": "f0b97bb2-2c35-42df-b0fb-9fecd01498ae",
"name": "Ensures the response has bookmarks before continuing",
"type": "n8n-nodes-base.if",
"position": [
-880,
200
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "25997115-4422-4d65-86aa-47c4ab3edb17",
"operator": {
"type": "array",
"operation": "lengthGt",
"rightType": "number"
},
"leftValue": "={{ $json.body }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a5b393c0-51ab-4422-a2d7-bf098b97b729",
"name": "Extracts pagination data (like next min_id) from HTTP headers",
"type": "n8n-nodes-base.code",
"position": [
-660,
200
],
"parameters": {
"jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nconst links = $input.first().json.headers.link;\nlet regexp = /(?:\\?|\\&)(?<key>[\\w]+)=(?<value>[\\w+,.-]+)/g;\nlet results = links.matchAll(regexp);\nfor (let match of results) {\n console.log(match.groups.key);\n let key = match.groups.key;\n console.log(match.groups.value);\n let value = match.groups.value;\n $input.last().json[key] = value;\n }\n\n\n\nreturn $input.all();"
},
"typeVersion": 2,
"alwaysOutputData": false
},
{
"id": "3117db2a-cc3f-45b8-94df-cb0290f18f87",
"name": "Saves the new min_id to workflow static data",
"type": "n8n-nodes-base.code",
"position": [
-440,
300
],
"parameters": {
"jsCode": "const workflowStaticData = $getWorkflowStaticData('global');\n\n// get new access token\nworkflowStaticData.min_id = $input.first().json.min_id ;\n// set timestamp of new access token\n\nreturn [\n {\n // data: $input.all(),\n accessToken: workflowStaticData.min_id,\n // today: $today\n }\n];"
},
"typeVersion": 2
},
{
"id": "e7c0cfbb-a0be-47f2-9ff2-26955c0678c4",
"name": "Splits API response into individual bookmark items",
"type": "n8n-nodes-base.splitOut",
"position": [
-440,
100
],
"parameters": {
"options": {},
"fieldToSplitOut": "=body"
},
"typeVersion": 1
},
{
"id": "813c1f01-2400-4e6c-a51a-1709bb2c27d3",
"name": "Filters out invalid or incomplete bookmark data",
"type": "n8n-nodes-base.if",
"position": [
-220,
100
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "10f21e21-f57e-49c1-94e0-7ea7d84dce24",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.card.url}}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e6620ed1-48c0-44ee-98de-d79bc1c801ab",
"name": "Saves valid bookmark using post metadata (e.g., title, card.url)",
"type": "n8n-nodes-base.raindrop",
"position": [
0,
0
],
"parameters": {
"link": "={{ $json.card.url }}",
"resource": "bookmark",
"operation": "create",
"collectionId": "=-1",
"additionalFields": {
"title": "={{ $json.card.title }}",
"pleaseParse": true
}
},
"credentials": {
"raindropOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "1a5d6393-207d-443c-ab76-ffb10a93f143",
"name": "Saves bookmark using alternate fields if card data is missing",
"type": "n8n-nodes-base.raindrop",
"position": [
0,
200
],
"parameters": {
"link": "={{ $json.url }}",
"resource": "bookmark",
"operation": "create",
"collectionId": "=-1",
"additionalFields": {
"title": "={{ $json.account.username }}",
"pleaseParse": true
}
},
"credentials": {
"raindropOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "19213b61-9f95-445f-8f28-a5de7868988d",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1800,
-380
],
"parameters": {
"width": 780,
"height": 400,
"content": "## \ud83d\uddc2\ufe0f Sync Mastodon Bookmarks to Raindrop\n\nThis workflow fetches your latest bookmarks from Mastodon and saves them to Raindrop.io, allowing you to organize and access saved posts outside of Mastodon.\n\n\ud83d\udd27 Requirements:\n\n A Mastodon access token with permission to read bookmarks\n\n A Raindrop.io OAuth2 credential\n\n Replace {VOTRE SERVEUR MASTODON} with your Mastodon server base URL (e.g., https://mastodon.social)\n\n First run will default to min_id = 0, then it updates to fetch only new bookmarks\n\n\ud83d\udd52 Triggered on schedule or manually\n\n\ud83d\udca1 Pagination data is extracted from HTTP headers to support future syncs without duplication."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "208d09f1-9aab-41a0-a6b6-ad6bc10c450f",
"connections": {
"Allows manual testing of the workflow": {
"main": [
[
{
"node": "Retrieves the last processed min_id to avoid duplicates",
"type": "main",
"index": 0
}
]
]
},
"Triggers the workflow on a set interval": {
"main": [
[
{
"node": "Retrieves the last processed min_id to avoid duplicates",
"type": "main",
"index": 0
}
]
]
},
"Filters out invalid or incomplete bookmark data": {
"main": [
[
{
"node": "Saves valid bookmark using post metadata (e.g., title, card.url)",
"type": "main",
"index": 0
}
],
[
{
"node": "Saves bookmark using alternate fields if card data is missing",
"type": "main",
"index": 0
}
]
]
},
"Splits API response into individual bookmark items": {
"main": [
[
{
"node": "Filters out invalid or incomplete bookmark data",
"type": "main",
"index": 0
}
]
]
},
"Ensures the response has bookmarks before continuing": {
"main": [
[
{
"node": "Extracts pagination data (like next min_id) from HTTP headers",
"type": "main",
"index": 0
}
]
]
},
"Retrieves the last processed min_id to avoid duplicates": {
"main": [
[
{
"node": "Makes authenticated request to Mastodon\u2019s bookmarks API",
"type": "main",
"index": 0
}
]
]
},
"Makes authenticated request to Mastodon\u2019s bookmarks API": {
"main": [
[
{
"node": "Ensures the response has bookmarks before continuing",
"type": "main",
"index": 0
}
]
]
},
"Extracts pagination data (like next min_id) from HTTP headers": {
"main": [
[
{
"node": "Splits API response into individual bookmark items",
"type": "main",
"index": 0
},
{
"node": "Saves the new min_id to workflow static data",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing β you'll add your own.
httpBearerAuthraindropOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
> π οΈ Note: This workflow uses a custom Mastodon API request. Ensure your server supports bookmark access, and that your access token has the right permissions. OAuth or token-based credentials must be configured.
Source: https://n8n.io/workflows/4800/ β original creator credit. Request a take-down β
More Web Scraping workflows β Β· Browse all categories β
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow allows you to import any workflow from a file or another n8n instance and map the credentials easily. A multi-form setup guides you through the entire process At the beginning you have t
[n8n] Advanced URL Parsing and Shortening Workflow - Switchy.io Integration. Uses splitInBatches, stickyNote, httpRequest, html. Event-driven trigger; 56 nodes.
[](https://youtu.be/c7yCZhmMjtI)
This automation organizes your n8n workflows files into categorizes (Active, Template, Done, Archived) and uploads them directly to a categorized Google Drive folders. It is designed to help users man
Create Animated Stories using GPT-4o-mini, Midjourney, Kling and Creatomate API. Uses httpRequest. Event-driven trigger; 51 nodes.