This workflow corresponds to n8n.io template #15971 — 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": "aTDgyK8SgbRowuQv",
"name": "Research Kuaishou video details from a keyword with JustOneAPI - real response adjusted",
"tags": [],
"nodes": [
{
"id": "270f60a0-faaf-4bc2-9b2c-a7f5336d5343",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1968,
1088
],
"parameters": {
"width": 496,
"height": 560,
"content": "## Research Kuaishou video details from a keyword with JustOneAPI - real response adjusted\n\n### How it works\n\n1. Trigger workflow manually to begin research process\n2. Prepare API parameters and user inputs for search\n3. Search Kuaishou videos using keyword input\n4. Extract video IDs from search results\n5. Check if valid video IDs exist\n6. Fetch detailed information for each valid video\n7. Compile video details into structured output\n\n### Setup steps\n\n- - [ ] Configure JustOneAPI credentials in n8n credentials store\n- - [ ] Set base URL for Kuaishou API endpoints\n- - [ ] Define required fields for video search and details retrieval\n\n### Customization\n\nThe workflow can be customized by:\n- Adding more search filters in the 'Prepare API and Research Inputs' node\n- Modifying the output fields in 'Build Video Detail List' node\n- Adjusting error handling in the conditional branch"
},
"typeVersion": 1
},
{
"id": "74f72780-96eb-45ea-bcdc-ad4fe8ab1d94",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
2528,
1088
],
"parameters": {
"color": 7,
"height": 112,
"content": "## Workflow Trigger\n\nManual initiation point for the research workflow"
},
"typeVersion": 1
},
{
"id": "2bed0707-0eaf-4b84-9153-4f6be5511f6a",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2912,
1088
],
"parameters": {
"color": 7,
"width": 272,
"height": 96,
"content": "## Input Preparation\n\nSets up API parameters and user inputs for search"
},
"typeVersion": 1
},
{
"id": "b5e732fa-8596-4747-a53b-996786b59089",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
3376,
1088
],
"parameters": {
"color": 7,
"width": 336,
"height": 112,
"content": "## Video Search Execution\n\nPerforms API call to search Kuaishou videos by keyword"
},
"typeVersion": 1
},
{
"id": "62e2ba4f-d42d-472a-88d8-d145b73c2440",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
3808,
1088
],
"parameters": {
"color": 7,
"width": 688,
"height": 112,
"content": "## Search Results Processing\n\nExtracts video IDs from search results and checks validity"
},
"typeVersion": 1
},
{
"id": "f15599d1-eeb4-4584-bf28-a463b5206c42",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
4592,
1088
],
"parameters": {
"color": 7,
"width": 304,
"height": 112,
"content": "## Video Details Retrieval\n\nFetches detailed information for each valid video ID"
},
"typeVersion": 1
},
{
"id": "191f9ea0-fe5a-4321-ab50-073bbf5d52a0",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
4928,
1088
],
"parameters": {
"color": 7,
"width": 496,
"height": 112,
"content": "## Results Compilation\n\nBuilds final structured output of video details"
},
"typeVersion": 1
},
{
"id": "67510f1b-a478-48da-bc7b-4c8f8505a5c9",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
3696,
1440
],
"parameters": {
"color": 7,
"width": 624,
"height": 272,
"content": "## Search Results Output\n\nOutputs raw search results for reference"
},
"typeVersion": 1
},
{
"id": "06f33d3b-1969-4e54-b361-c404127fcfcb",
"name": "Manual Trigger Start",
"type": "n8n-nodes-base.manualTrigger",
"position": [
2576,
1248
],
"parameters": {},
"typeVersion": 1
},
{
"id": "9a58fb21-f3f1-427a-b25f-417915d44ba9",
"name": "Prepare API and Research Fields",
"type": "n8n-nodes-base.set",
"position": [
2960,
1248
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "{\n \"baseUrl\": \"https://api.justoneapi.com\",\n \"token\": \"YOUR_JUSTONEAPI_TOKEN\",\n \"keyword\": \"YOUR_SEARCH_KEYWORD\",\n \"page\": 1,\n \"maxVideos\": 1\n}"
},
"typeVersion": 3.4
},
{
"id": "28b8a25c-b17d-49bf-8e87-4f68dce619ea",
"name": "Search Kuaishou Videos via API",
"type": "n8n-nodes-base.httpRequest",
"position": [
3424,
1248
],
"parameters": {
"url": "={{$json.baseUrl + '/api/kuaishou/search-video/v2'}}",
"options": {
"redirect": {
"redirect": {}
}
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "token",
"value": "={{$json.token}}"
},
{
"name": "keyword",
"value": "={{$json.keyword}}"
},
{
"name": "page",
"value": "={{$json.page}}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "8b6c1388-f870-4b62-8766-41e35dd4a389",
"name": "Output Search Video Results",
"type": "n8n-nodes-base.set",
"position": [
3744,
1552
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{$json}}"
},
"typeVersion": 3.4
},
{
"id": "c7f8e924-ed6d-4116-93eb-a78a618ba12d",
"name": "Extract Video IDs with Code",
"type": "n8n-nodes-base.code",
"position": [
3856,
1248
],
"parameters": {
"jsCode": "const root = $input.first().json || {};\nconst config = $('Prepare API and Research Fields').first().json || {};\nconst maxVideos = Math.max(1, Number(config.maxVideos || 1));\nconst seen = new Set();\nconst candidates = [];\n\nfunction getApiResponse(value) {\n if (Array.isArray(value)) return value[0] || {};\n return value || {};\n}\n\nfunction extractClientCacheKey(url) {\n if (!url) return '';\n const text = String(url);\n const match = text.match(/[?&]clientCacheKey=([^&]+)/i);\n if (!match) return '';\n return decodeURIComponent(match[1])\n .replace(/\\.(jpg|jpeg|png|webp|mp4)$/i, '')\n .trim();\n}\n\nfunction pushCandidate(videoId, source, item) {\n if (!videoId || seen.has(videoId)) return;\n seen.add(videoId);\n candidates.push({\n videoId,\n videoIdSource: source,\n searchItem: item || null\n });\n}\n\nfunction urlsFromList(list) {\n if (!Array.isArray(list)) return [];\n return list.map(entry => {\n if (typeof entry === 'string') return entry;\n if (entry && typeof entry === 'object') return entry.url || '';\n return '';\n }).filter(Boolean);\n}\n\nconst response = getApiResponse(root);\nconst data = response.data || {};\nconst feeds = Array.isArray(data.feeds) ? data.feeds : [];\n\nfor (const feed of feeds) {\n const candidateUrls = [\n feed.main_url,\n feed.thumbnail_url,\n ...urlsFromList(feed.cover_thumbnail_urls),\n ...urlsFromList(feed.thumbnail_urls)\n ].filter(Boolean);\n\n for (const url of candidateUrls) {\n const videoId = extractClientCacheKey(url);\n if (videoId) {\n pushCandidate(videoId, 'data.feeds[].main_url/cover clientCacheKey', feed);\n break;\n }\n }\n\n if (candidates.length >= maxVideos) break;\n}\n\nconst selected = candidates.slice(0, maxVideos);\n\nif (selected.length === 0) {\n return [\n {\n json: {\n error: 'No detail videoId was extracted from data.feeds[].main_url or cover URL clientCacheKey fields in the search response.',\n baseUrl: config.baseUrl,\n token: config.token,\n keyword: config.keyword,\n page: config.page,\n maxVideos,\n rawSearchResponse: root\n }\n }\n ];\n}\n\nreturn selected.map(candidate => ({\n json: {\n baseUrl: config.baseUrl,\n token: config.token,\n keyword: config.keyword,\n page: config.page,\n maxVideos,\n videoId: candidate.videoId,\n videoIdSource: candidate.videoIdSource,\n searchItem: candidate.searchItem,\n rawSearchResponse: root\n }\n}));"
},
"typeVersion": 2
},
{
"id": "b2285fd5-05ca-47be-a8d5-dc895e405780",
"name": "Output Extracted Video IDs",
"type": "n8n-nodes-base.set",
"position": [
4176,
1552
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{$json}}"
},
"typeVersion": 3.4
},
{
"id": "5fb4b4c9-ec65-41fe-8c09-1173bd3107e5",
"name": "If Video ID Exists",
"type": "n8n-nodes-base.if",
"position": [
4304,
1248
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "39ae3245-966b-4971-a7f0-0fe3033612e8",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{$json.videoId}}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "badcd4db-7370-45a3-bdfb-89b96c3a20d6",
"name": "Fetch Video Details via API",
"type": "n8n-nodes-base.httpRequest",
"position": [
4640,
1248
],
"parameters": {
"url": "={{$json.baseUrl + '/api/kuaishou/get-video-detail/v2'}}",
"options": {
"redirect": {
"redirect": {}
}
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "token",
"value": "={{$json.token}}"
},
{
"name": "videoId",
"value": "={{$json.videoId}}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "d78b25e6-7450-4ff5-a967-0e5504602c0d",
"name": "Build Video Details with Code",
"type": "n8n-nodes-base.code",
"position": [
4976,
1248
],
"parameters": {
"jsCode": "const rows = $input.all();\nconst extractedRows = $('Extract Video IDs with Code').all();\nconst config = $('Prepare API and Research Fields').first().json || {};\n\nfunction firstArray(...values) {\n for (const value of values) {\n if (Array.isArray(value) && value.length > 0) return value;\n }\n return [];\n}\n\nfunction firstUrl(list) {\n if (!Array.isArray(list) || list.length === 0) return '';\n const first = list[0];\n if (typeof first === 'string') return first;\n if (first && typeof first === 'object') return first.url || '';\n return '';\n}\n\nfunction getApiResponse(value) {\n if (Array.isArray(value)) return value[0] || {};\n return value || {};\n}\n\nfunction getRepresentations(photo) {\n const adaptationSet = photo?.streamManifest?.adaptationSet || [];\n const representations = [];\n for (const set of adaptationSet) {\n for (const rep of (set.representation || [])) {\n representations.push(rep);\n }\n }\n return representations;\n}\n\nfunction normalizeSearchItem(searchItem) {\n if (!searchItem || typeof searchItem !== 'object') return {};\n return {\n caption: searchItem.caption || '',\n authorName: searchItem.user_name || '',\n authorId: searchItem.user_id ?? '',\n kwaiId: searchItem.kwaiId || '',\n publishTime: searchItem.time || '',\n timestamp: searchItem.timestamp ?? '',\n photoId: searchItem.photo_id ?? '',\n likeCount: searchItem.like_count ?? '',\n commentCount: searchItem.comment_count ?? '',\n shareCount: searchItem.share_count ?? '',\n viewCount: searchItem.view_count ?? '',\n durationMs: searchItem.duration ?? '',\n coverUrl: searchItem.main_url || searchItem.thumbnail_url || firstUrl(searchItem.cover_thumbnail_urls) || firstUrl(searchItem.thumbnail_urls),\n previewVideoUrl: searchItem.main_mv_url || firstUrl(searchItem.main_mv_urls),\n width: searchItem.ext_params?.w ?? '',\n height: searchItem.ext_params?.h ?? ''\n };\n}\n\nfunction normalizeDetailPhoto(photo) {\n if (!photo || typeof photo !== 'object') return {};\n const representations = getRepresentations(photo);\n const firstRep = representations[0] || {};\n return {\n caption: photo.caption || '',\n authorName: photo.user_name || '',\n authorId: photo.user_id ?? '',\n kwaiId: photo.kwaiId || '',\n publishTime: photo.time || '',\n timestamp: photo.timestamp ?? '',\n photoId: photo.photo_id ?? '',\n likeCount: photo.like_count ?? '',\n commentCount: photo.comment_count ?? '',\n shareCount: photo.share_count ?? '',\n viewCount: photo.view_count ?? '',\n collectCount: photo.collect_count ?? '',\n durationMs: photo.duration ?? '',\n coverUrl: photo.main_url || photo.thumbnail_url || firstUrl(photo.cover_thumbnail_urls) || firstUrl(photo.thumbnail_urls),\n videoUrl: firstRep.url || photo.main_mv_url || firstUrl(photo.main_mv_urls),\n backupVideoUrls: firstArray(firstRep.backupUrl),\n streamVideoId: photo.streamManifest?.videoId || '',\n mediaWidth: firstRep.width ?? photo.ext_params?.w ?? '',\n mediaHeight: firstRep.height ?? photo.ext_params?.h ?? '',\n qualityLabel: firstRep.qualityLabel || '',\n qualityType: firstRep.qualityType || ''\n };\n}\n\nreturn rows.map((item, index) => {\n const detailResponse = item.json || {};\n const extracted = extractedRows[index]?.json || extractedRows[0]?.json || {};\n const detailApiResponse = getApiResponse(detailResponse);\n const detailData = detailApiResponse.data || {};\n const photos = Array.isArray(detailData.photos) ? detailData.photos : [];\n const detailPhoto = photos[0] || {};\n const searchItem = extracted.searchItem || {};\n\n return {\n json: {\n requestedKeyword: config.keyword || extracted.keyword || '',\n page: extracted.page ?? config.page ?? '',\n videoId: extracted.videoId || '',\n videoIdSource: extracted.videoIdSource || '',\n searchVideo: normalizeSearchItem(searchItem),\n detailVideo: normalizeDetailPhoto(detailPhoto),\n debug: {\n searchResultCount: Array.isArray(getApiResponse(extracted.rawSearchResponse).data?.feeds) ? getApiResponse(extracted.rawSearchResponse).data.feeds.length : 0,\n detailPhotoCount: photos.length,\n detailResult: detailData.result ?? '',\n detailApiCode: detailApiResponse.code ?? '',\n detailApiMessage: detailApiResponse.message ?? ''\n },\n raw: {\n selectedSearchItem: searchItem,\n searchResponse: extracted.rawSearchResponse || null,\n detailPhoto,\n detailResponse\n }\n }\n };\n});"
},
"typeVersion": 2
},
{
"id": "c904f8a7-f461-416f-8b1e-48cf2bcc8c7f",
"name": "Output Video Details List",
"type": "n8n-nodes-base.set",
"position": [
5296,
1248
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{$json}}"
},
"typeVersion": 3.4
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "2d81fdd2-0a66-4676-9ae6-87f49003ddba",
"connections": {
"If Video ID Exists": {
"main": [
[
{
"node": "Fetch Video Details via API",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger Start": {
"main": [
[
{
"node": "Prepare API and Research Fields",
"type": "main",
"index": 0
}
]
]
},
"Extract Video IDs with Code": {
"main": [
[
{
"node": "Output Extracted Video IDs",
"type": "main",
"index": 0
},
{
"node": "If Video ID Exists",
"type": "main",
"index": 0
}
]
]
},
"Fetch Video Details via API": {
"main": [
[
{
"node": "Build Video Details with Code",
"type": "main",
"index": 0
}
]
]
},
"Build Video Details with Code": {
"main": [
[
{
"node": "Output Video Details List",
"type": "main",
"index": 0
}
]
]
},
"Search Kuaishou Videos via API": {
"main": [
[
{
"node": "Output Search Video Results",
"type": "main",
"index": 0
},
{
"node": "Extract Video IDs with Code",
"type": "main",
"index": 0
}
]
]
},
"Prepare API and Research Fields": {
"main": [
[
{
"node": "Search Kuaishou Videos via API",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs manually to search Kuaishou videos by a keyword using JustOneAPI, extracts a video ID from the search response, then retrieves and outputs normalized video detail fields along with debug information. Runs when you manually start the workflow. Sets the…
Source: https://n8n.io/workflows/15971/ — original creator credit. Request a take-down →
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.