버그 바운티 정보 수집기
중급
이것은Market Research, Multimodal AI분야의자동화 워크플로우로, 8개의 노드를 포함합니다.주로 Code, HttpRequest, GoogleSheets, ScheduleTrigger 등의 노드를 사용하며. Twitter 버그 바운티 힌트 Google 시트 자동 수집
사전 요구사항
- •대상 API의 인증 정보가 필요할 수 있음
- •Google Sheets API 인증 정보
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
"id": "Hl5YR8MHd1AyDYXk",
"meta": {
"instanceId": "c5257b5cf4d48704d636909c07c4408a69d6799d0a855eab46287eeb702c84b0",
"templateCredsSetupCompleted": true
},
"name": "BB Tip Harvestor",
"tags": [],
"nodes": [
{
"id": "95247308-430c-4f13-bc7d-98beecb5b945",
"name": "일정 트리거",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
320,
80
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 4
}
]
}
},
"typeVersion": 1.2
},
{
"id": "6b347ec0-fb37-4ce8-889f-2b29bc1b2e1b",
"name": "📒 워크플로우 개요",
"type": "n8n-nodes-base.stickyNote",
"position": [
-272,
16
],
"parameters": {
"color": 4,
"width": 480,
"height": 232,
"content": "## 🎯 Bug Bounty Tip Harvester\n\nAutomatically collects bug bounty tips from Twitter every 4 hours and saves to Google Sheets.\n\n**Setup required:**\n1. Get API key from https://twitterapi.io/\n2. Configure Google Sheets credentials\n3. Update Google Sheet ID"
},
"typeVersion": 1
},
{
"id": "fa97a28d-cb1c-4e37-8272-3b6efc7f1a44",
"name": "HTTP 요청",
"type": "n8n-nodes-base.httpRequest",
"position": [
544,
80
],
"parameters": {
"url": "https://api.twitterapi.io/twitter/tweet/advanced_search",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "query",
"value": "(#bugbountytips OR #bugbounty OR #bugbountytip) -Writeups -discount -phishing -fuck"
},
{
"name": "queryType",
"value": "Latest"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"id": "OlMRj5cL1g7C7eNH",
"name": "Twitterapi.io Xcal"
}
},
"typeVersion": 4.2
},
{
"id": "d7ef4868-ef6b-4a57-95f4-b987dbcea50c",
"name": "📒 Twitter API",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
-256
],
"parameters": {
"color": 2,
"width": 348,
"height": 198,
"content": "## 🔐 Twitter API Setup\n\n1. Sign up at https://twitterapi.io/\n2. Get your API key\n3. Add HTTP Header Auth:\n - **Header**: `x-api-key`\n - **Value**: `YOUR_API_KEY`"
},
"typeVersion": 1
},
{
"id": "e76166b2-e6e4-4543-aad2-68bc8885d231",
"name": "코드",
"type": "n8n-nodes-base.code",
"position": [
752,
80
],
"parameters": {
"jsCode": "// This approach handles both single tweets and collections\n// It focuses on properly formatting the output for n8n\n\nconsole.log(\"Input item structure:\", JSON.stringify($input.item, null, 2));\n\n// Function to format the date in a more human-readable way\nfunction formatDate(dateString) {\n if (!dateString) return '';\n\n try {\n const date = new Date(dateString);\n // Format: \"March 13, 2025 at 19:25\"\n return date.toLocaleString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n } catch (error) {\n console.log(\"Error formatting date:\", error);\n return dateString; // Return original if parsing fails\n }\n}\n\n// Check if this is a Twitter Search result with multiple tweets\nif ($input.item.json.tweets && Array.isArray($input.item.json.tweets)) {\n const items = $input.item.json.tweets.map(tweet => {\n return {\n json: {\n tweetId: tweet.id || '',\n url: tweet.url || '',\n content: tweet.text || '',\n likeCount: tweet.likeCount || 0,\n retweetCount: tweet.retweetCount || 0,\n replyCount: tweet.replyCount || 0,\n quoteCount: tweet.quoteCount || 0,\n viewCount: tweet.viewCount || 0,\n createdAt: formatDate(tweet.createdAt),\n }\n };\n });\n\n console.log(`Processing ${items.length} tweets`);\n // Return all items\n return items;\n} else {\n // This is a single tweet. Just extract and return its data\n const tweetData = {\n tweetId: $input.item.json.id || '',\n url: $input.item.json.url || '',\n content: $input.item.json.text || '',\n likeCount: $input.item.json.likeCount || 0,\n retweetCount: $input.item.json.retweetCount || 0,\n replyCount: $input.item.json.replyCount || 0,\n quoteCount: $input.item.json.quoteCount || 0,\n viewCount: $input.item.json.viewCount || 0,\n createdAt: formatDate($input.item.json.createdAt)\n };\n\n console.log(\"Processing single tweet\");\n\n // Return as a single item\n return {\n json: tweetData\n };\n}"
},
"typeVersion": 2
},
{
"id": "ca01565b-ded3-42af-832c-0662f0ea2c4d",
"name": "📒 데이터 처리",
"type": "n8n-nodes-base.stickyNote",
"position": [
736,
368
],
"parameters": {
"color": 3,
"width": 376,
"height": 168,
"content": "## ⚙️ Data Processing\n\nExtracts tweet data and formats for Google Sheets:\n- Tweet content, URLs, engagement metrics\n- Date formatting for proper sorting\n- Handles both single tweets and collections"
},
"typeVersion": 1
},
{
"id": "ed06b8aa-c7ac-4e69-8e19-c2ce422f2bdb",
"name": "Append or update row in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
992,
80
],
"parameters": {
"columns": {
"value": {
"Url": "={{ $json.url }}",
"Date": "={{ \n (() => {\n const raw = $json.createdAt; // e.g. \"July 7, 2025 at 04:43 AM\"\n const [monthStr, day, yearTime, , time, meridian] = raw.split(/[\\s,]+/);\n const months = {\n January: \"01\", February: \"02\", March: \"03\", April: \"04\", May: \"05\", June: \"06\",\n July: \"07\", August: \"08\", September: \"09\", October: \"10\", November: \"11\", December: \"12\"\n };\n\n const [hour, minute] = time.split(\":\").map(Number);\n let hh = meridian === \"PM\" && hour !== 12 ? hour + 12 : (meridian === \"AM\" && hour === 12 ? 0 : hour);\n const formattedHour = String(hh).padStart(2, '0');\n\n return `${yearTime}-${months[monthStr]}-${String(day).padStart(2, '0')} ${formattedHour}:${minute}:00`;\n })() \n}}",
"Content": "={{ $json.content }}",
"TweetID": "={{ $json.tweetId }}",
"Created At": "={{ $json.createdAt }}"
},
"schema": [
{
"id": "Content",
"type": "string",
"display": true,
"required": false,
"displayName": "Content",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "TweetID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "TweetID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Url",
"type": "string",
"display": true,
"required": false,
"displayName": "Url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Created At",
"type": "string",
"display": true,
"required": false,
"displayName": "Created At",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"TweetID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultUrl": "",
"cachedResultName": "Your Google Sheet"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "GniS74XmPh4KjdoT",
"name": "Google Sheets beethical"
}
},
"typeVersion": 4.6
},
{
"id": "462cb2c0-136f-454e-9e32-f7fe734c51a9",
"name": "📊 Google 스프레드시트",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
-64
],
"parameters": {
"color": 5,
"width": 448,
"height": 198,
"content": "## 📊 Google Sheets Setup\n\n1. Create Google Sheet with columns: Date, Created At, TweetID, Content, Url\n2. Set up Google Sheets OAuth2 credentials\n3. Replace empty documentId with your Sheet ID\n\n**Prevents duplicates using TweetID matching**"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "65c1d539-9a53-41ed-af0a-330c314826b9",
"connections": {
"Code": {
"main": [
[
{
"node": "ed06b8aa-c7ac-4e69-8e19-c2ce422f2bdb",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
}
}
}자주 묻는 질문
이 워크플로우를 어떻게 사용하나요?
위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.
이 워크플로우는 어떤 시나리오에 적합한가요?
중급 - 시장 조사, 멀티모달 AI
유료인가요?
이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.
관련 워크플로우 추천
MetaAds 크리에이티브 인사이트 연구원 v1.4
Google Vision 및 Video Intelligence API를 사용하여 Meta 광고 크리에이티브 분석
If
Set
Code
+
If
Set
Code
32 노드Kirill Khatkevich
시장 조사
YouTube 댓글 감정 및 키워드 추출기
Gemini AI를 사용하여 YouTube 댓글 감성 및 키워드 분석 및 Telegram으로 보고
Set
Code
Telegram
+
Set
Code
Telegram
20 노드Budi SJ
시장 조사
ApiFlash, Gemini Vision 및 Sheets에서 Telegram으로의 자동 기술 뉴스 리포트
통해ApiFlash、Gemini Vision및Sheets로Telegram의자동화科技新闻보고서
Set
Code
Limit
+
Set
Code
Limit
18 노드Cong Nguyen
시장 조사
10 - 비즈니스 버전 추적기
SerpAPI, Google 스프레드시트 및 Airtable을 사용한 일일 경쟁자 연구 자동화
If
Code
Airtable
+
If
Code
Airtable
15 노드Avkash Kakdiya
시장 조사
매일 Google 광고 성과를 Notion과 Google Sheets로 동기화
매일 Google 광고 성과를 Notion과 Google Sheets로 동기화
Set
Code
Merge
+
Set
Code
Merge
19 노드Aziz dev
시장 조사
최고의 백링크 체커 API를 사용한 웹사이트 백링크 분석 및 Google Sheets에 기록
최고의 백링크 검사기 API를 사용하여 웹사이트 백링크 분석 및 Google Sheets에 기록
Code
Form Trigger
Http Request
+
Code
Form Trigger
Http Request
13 노드Sk developer
시장 조사