This workflow corresponds to n8n.io template #12221 — we link there as the canonical source.
This workflow follows the HTTP Request → Slack recipe pattern — see all workflows that pair these two integrations.
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": "slQj31557EQFAMTs",
"name": "Phishing Lookout and Brand Domain Monitor Workflow",
"tags": [],
"nodes": [
{
"id": "5a9b9b55-f3b5-4dad-9dd3-b08bf725f0dd",
"name": "Schedule (Every Hour)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
592,
576
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours"
}
]
}
},
"typeVersion": 1
},
{
"id": "a6fdb539-8f90-4090-9bf2-3224081ae2e6",
"name": "Poll crt.sh (SSL Logs)",
"type": "n8n-nodes-base.httpRequest",
"notes": "Queries public SSL logs for any certificate containing 'testyourdomain.com'. CHANGE the URL query to your target brand.",
"maxTries": 5,
"position": [
816,
576
],
"parameters": {
"url": "=https://crt.sh/?q=%.testdomain.com&output=json",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.1,
"waitBetweenTries": 5000
},
{
"id": "1de5d4c1-e5f5-4cb9-b032-cd8d24df5313",
"name": "Filter & Deduplicate",
"type": "n8n-nodes-base.code",
"position": [
1264,
576
],
"parameters": {
"jsCode": "// 1. Configuration\n\n// Add domains to IGNORE here. You may Exclude your own domain to test how Workflow behaves but eventually add your domain below so it doesnt appear in final Alerts output \nconst myDomains =[\"yourdomain.com\",\"testdomain.com\",\"google.com\"]; \n\n// value in Hrs. reduce the hours if most recent data is needed from crt.sh\nconst hoursAgo = 4000; \nconst cutoffDate = new Date();\ncutoffDate.setHours(cutoffDate.getHours() - hoursAgo);\n\nconst alerts = [];\nconst seenDomains = new Set();\n\n// 2. Processing\nitems.forEach(item => {\n // Use name_value from the item (Split Out creates these)\n const domain = item.json.name_value || \"\";\n \n // Use entry_timestamp if available, otherwise use current date for testing\n const rawDate = item.json.entry_timestamp || new Date().toISOString();\n const certDate = new Date(rawDate);\n\n // Clean wildcard prefixes (*.)\n const cleanDomain = domain.replace(/^\\*\\./, '');\n\n // LOGIC CHECKS\n const isNew = certDate > cutoffDate;\n const isSuspicious = !myDomains.includes(cleanDomain);\n const isUnique = !seenDomains.has(cleanDomain);\n const isNotEmpty = cleanDomain.length > 0;\n\n if (isNew && isSuspicious && isUnique && isNotEmpty) {\n seenDomains.add(cleanDomain);\n alerts.push({ json: { domain: cleanDomain, date: certDate } });\n }\n});\n\nreturn alerts;"
},
"typeVersion": 2
},
{
"id": "5b663bf6-4fab-43be-9481-13b5d410f09e",
"name": "Split In Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1488,
576
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "179f2924-4a59-4cb9-9f29-11f611c432d1",
"name": "Wait for Scan",
"type": "n8n-nodes-base.wait",
"notes": "Wait 45s for urlscan to generate the screenshot.",
"position": [
1920,
512
],
"parameters": {
"unit": "seconds",
"amount": 30
},
"typeVersion": 1
},
{
"id": "aaa47290-fbba-4a6e-8316-e550bfad4ebe",
"name": "Alert Slack",
"type": "n8n-nodes-base.slack",
"position": [
2384,
576
],
"parameters": {
"text": "=\u26a0\ufe0f *Suspicious Brand Domain Detected*\n\n*Domain:* {{ $node[\"Split In Batches\"].json[\"domain\"] }} \n*Scan Report:* {{ $('Perform a scan').item.json.result }}\n*Screenshot:* {{ $json.task.screenshotURL }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C0917N0QN2C",
"cachedResultName": "content-creation-agent"
},
"otherOptions": {
"unfurl_media": true
}
},
"typeVersion": 2.1
},
{
"id": "211e55b8-1516-48b8-aee4-e02169108bde",
"name": "Perform a scan",
"type": "n8n-nodes-base.urlScanIo",
"position": [
1712,
512
],
"parameters": {
"url": "={{ $json.domain }}",
"additionalFields": {}
},
"typeVersion": 1
},
{
"id": "c525fb48-1552-417c-a472-cbaf104d91cb",
"name": "Get a scan",
"type": "n8n-nodes-base.urlScanIo",
"position": [
2160,
512
],
"parameters": {
"scanId": "={{ $json.scanId }}",
"operation": "get"
},
"typeVersion": 1
},
{
"id": "a9b666e6-a7b5-4b67-92e4-3a8f431cb99a",
"name": "Split Out",
"type": "n8n-nodes-base.splitOut",
"position": [
1040,
576
],
"parameters": {
"options": {},
"fieldToSplitOut": "name_value"
},
"typeVersion": 1
},
{
"id": "4b7fb101-dc9d-4b7b-af93-08a3d91512be",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 544,
"height": 992,
"content": "## Phishing Lookout: Brand Impersonation Monitor\nThis workflow monitors SSL certificate logs to find and scan new domains that might be impersonating your brand.\n\n## Background\nIn modern cybersecurity, Brand Impersonation (or \"Typosquatting\") is quite common in phishing attacks. Attackers register domains that look nearly identical to a trusted brand\u2014such as .xyz-n8n.io, n8n.i0, etc. instead of the legitimate\u2014 to deceive users into revealing sensitive credentials or downloading malware.\n\n## How it works\nMonitor: Checks crt.sh every hour for new SSL certificates matching your brand keywords.\n\nProcess: Uses a Split Out node to handle multi-domain certificates and a Filter node to ignore your own legitimate domains.\n\nScan: Automatically sends suspicious domains to Urlscan.io for a headless browser scan and screenshot.\n\nTriage: Implements a 90-second Wait to allow the scan to finish before fetching results.\n\nAlert: Sends a Slack message with the domain name, report link, and an image of the supposedly suspicious site trying to mimic your site login page, etc. for phishing.\n\n## Setup Steps\nCredentials: Connect your Urlscan.io API key and Slack bot token.\n\nConfiguration: Update the \"Poll crt.sh\" node. \nIn URL https://crt.sh/?q=%.testdomain.com&output=json, use your specific brand name (e.g., %.yourbrand.com or .yourdomain.com instead of .testdomain.com).\n\nWhitelist: Add your real domains to the myDomains list in the Filter & Deduplicate code node to prevent false alerts. Alternatively, you may also NOT opt to include your own domain for testing purposes to check how the Workflow behaves and outputs. In such case, obviously, your domain and sub-domains also are highlighted as Suspicious (as received in Slack Alerts)\n\nLooping: Ensure the Alert Slack node output is connected back to the Split In Batches input to process all found domains.\n"
},
"typeVersion": 1
},
{
"id": "0d84061a-e93e-4761-bda9-97201e6ea4c8",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
784,
384
],
"parameters": {
"color": 7,
"width": 384,
"height": 352,
"content": "## Poll crt.sh\n- Searches the crt.sh database for new SSL certificates using wildcard queries (e.g., %.testdomain.com).\n- Configured with Retry on Fail to handle intermittent \n502/504 errors from the public database.\n- Split items (domains) into separate items just in case"
},
"typeVersion": 1
},
{
"id": "8fff4d5e-27e6-407c-b4ca-730bed75ac92",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1184,
304
],
"parameters": {
"color": 7,
"width": 256,
"height": 432,
"content": "## Filter & Deduplicate\n- Only allows domains with certificates registered within the last 'x' hours.\n- Uses a myDomains list to exclude your company's legitimate domains from the scan. (Productive scenario)\n- Deduplication: Ensures the same domain isn't scanned multiple times in the same run."
},
"typeVersion": 1
},
{
"id": "87a20b0b-144a-4900-b348-2d775e6bd356",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1648,
192
],
"parameters": {
"color": 7,
"width": 640,
"height": 528,
"content": "## Perform scan, Wait, Get results in loop \nScan Trigger: Submits the suspicious URL to Urlscan.io for a safe, remote headless browser analysis.\nCaptures the uuid (Scan ID) needed to retrieve the results in the next step.\n### Wait for Scan\nPauses the workflow for 90 seconds to allow the remote browser to finish loading the site and taking a screenshot.\nPrevents \"resource not found\" errors during the retrieval step.\n### Get a scan\nUses the Scan ID to fetch the final report, including the site \"screenshot\" and technical risk data. Gets visual evidence of the malicious site into the workflow."
},
"typeVersion": 1
},
{
"id": "07a336f5-9efd-4c0a-ab8b-abbb0e1aa4a7",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2320,
288
],
"parameters": {
"color": 7,
"width": 256,
"height": 432,
"content": "## Alert Slack\nNotification: Sends an alert to the security channel containing the malicious site, domain, report link, and site screenshot.\n\nNote, \"Unfurl Media\" is enabled to display the screenshot directly in the chat for instant triage."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "4b87d664-8537-41b4-b83a-3362c1bd4759",
"connections": {
"Split Out": {
"main": [
[
{
"node": "Filter & Deduplicate",
"type": "main",
"index": 0
}
]
]
},
"Get a scan": {
"main": [
[
{
"node": "Alert Slack",
"type": "main",
"index": 0
}
]
]
},
"Alert Slack": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"Wait for Scan": {
"main": [
[
{
"node": "Get a scan",
"type": "main",
"index": 0
}
]
]
},
"Perform a scan": {
"main": [
[
{
"node": "Wait for Scan",
"type": "main",
"index": 0
}
]
]
},
"Split In Batches": {
"main": [
[],
[
{
"node": "Perform a scan",
"type": "main",
"index": 0
}
]
]
},
"Filter & Deduplicate": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"Schedule (Every Hour)": {
"main": [
[
{
"node": "Poll crt.sh (SSL Logs)",
"type": "main",
"index": 0
}
]
]
},
"Poll crt.sh (SSL Logs)": {
"main": [
[
{
"node": "Split Out",
"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 monitors SSL certificate logs to find and scan new domains that might be impersonating your brand.
Source: https://n8n.io/workflows/12221/ — 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 is an automated employee time tracking and reporting system that monitors weekly work hours via TMetric, then delivers personalized summaries directly to each team member on Slack. It co
Import Productboard Notes Companies And Features Into Snowflake. Uses stickyNote, httpRequest, splitOut, snowflake. Scheduled trigger; 35 nodes.
Import Productboard Notes, Companies and Features into Snowflake. Uses stickyNote, httpRequest, splitOut, snowflake. Scheduled trigger; 35 nodes.
This workflow imports Productboard data into Snowflake, automating data extraction, mapping, and updates for features, companies, and notes. It supports scheduled weekly updates, data cleansing, and S
This workflow streamlines the entire inventory replenishment process by leveraging AI for demand forecasting and intelligent logic for supplier selection. It aggregates data from multiple sources—POS