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 →
{
"name": "Proxy Tunnel Heartbeat \u2014 Hysteria2 / Residential Monitor + Telegram Alerts",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 5
}
]
}
},
"id": "c3d4e5f6-0001-4a5b-9c0d-333333333301",
"name": "Schedule \u2014 Every 5 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
240,
360
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "python",
"pythonCode": "import json\n\n# Tunnel & proxy endpoint registry\nENDPOINTS = [\n {\n 'name': 'Hysteria2-US-East',\n 'type': 'hysteria2',\n 'health_url': 'https://us-east.hy2.tunnel.local:48443/health',\n 'fallback_proxy': 'residential-us-01.proxyfleet.io:1080',\n 'priority': 1\n },\n {\n 'name': 'Hysteria2-EU-West',\n 'type': 'hysteria2',\n 'health_url': 'https://eu-west.hy2.tunnel.local:48443/health',\n 'fallback_proxy': 'residential-eu-02.proxyfleet.io:1080',\n 'priority': 2\n },\n {\n 'name': 'Hysteria2-AP-South',\n 'type': 'hysteria2',\n 'health_url': 'https://ap-south.hy2.tunnel.local:48443/health',\n 'fallback_proxy': 'residential-ap-03.proxyfleet.io:1080',\n 'priority': 3\n },\n {\n 'name': 'Residential-UK-Backup',\n 'type': 'residential',\n 'health_url': 'https://httpbin.org/ip',\n 'fallback_proxy': 'residential-uk-04.proxyfleet.io:1080',\n 'priority': 4\n }\n]\n\nreturn [{'json': ep} for ep in ENDPOINTS]"
},
"id": "c3d4e5f6-0002-4a5b-9c0d-333333333302",
"name": "Python \u2014 Load Tunnel Registry",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
480,
360
]
},
{
"parameters": {
"method": "GET",
"url": "={{ $json.health_url }}",
"options": {
"timeout": 15000,
"allowUnauthorizedCerts": true,
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"id": "c3d4e5f6-0003-4a5b-9c0d-333333333303",
"name": "HTTP \u2014 Ping Endpoint",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
720,
360
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "python",
"pythonCode": "import time\n\nitems = _input.all()\nresults = []\nfor item in items:\n status_code = item.json.get('statusCode', item.json.get('status_code', 0))\n endpoint_name = item.json.get('name', 'unknown')\n endpoint_type = item.json.get('type', 'unknown')\n fallback = item.json.get('fallback_proxy', '')\n priority = item.json.get('priority', 99)\n \n is_healthy = status_code == 200\n \n results.append({\n 'json': {\n 'endpoint_name': endpoint_name,\n 'endpoint_type': endpoint_type,\n 'status_code': status_code,\n 'is_healthy': is_healthy,\n 'fallback_proxy': fallback,\n 'priority': priority,\n 'checked_at': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),\n 'action': 'none' if is_healthy else 'switch_to_fallback'\n }\n })\nreturn results"
},
"id": "c3d4e5f6-0004-4a5b-9c0d-333333333304",
"name": "Python \u2014 Evaluate Health Status",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
960,
360
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "unhealthy-check",
"leftValue": "={{ $json.status_code }}",
"rightValue": 200,
"operator": {
"type": "number",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "c3d4e5f6-0005-4a5b-9c0d-333333333305",
"name": "IF \u2014 status_code != 200?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1200,
360
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "python",
"pythonCode": "import json\n\nitems = _input.all()\nresults = []\nfor item in items:\n endpoint = item.json.get('endpoint_name', '')\n fallback = item.json.get('fallback_proxy', '')\n status = item.json.get('status_code', 0)\n ep_type = item.json.get('endpoint_type', '')\n \n switch_config = {\n 'active_tunnel': fallback,\n 'previous_tunnel': endpoint,\n 'tunnel_type': ep_type,\n 'switched_at': item.json.get('checked_at', ''),\n 'reason': f'Health check failed with status {status}'\n }\n \n results.append({\n 'json': {\n **item.json,\n 'switch_config': switch_config,\n 'alert_message': f\"\ud83d\udea8 TUNNEL DOWN\\n\\nEndpoint: {endpoint}\\nType: {ep_type}\\nStatus: {status}\\nAction: Switching to {fallback}\\nTime: {item.json.get('checked_at', '')}\"\n }\n })\nreturn results"
},
"id": "c3d4e5f6-0006-4a5b-9c0d-333333333306",
"name": "Python \u2014 Switch to Fallback Proxy",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1440,
260
]
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"chat_id\": \"{{ $env.TELEGRAM_CHAT_ID }}\",\n \"text\": \"{{ $json.alert_message }}\",\n \"parse_mode\": \"HTML\",\n \"disable_web_page_preview\": true\n}",
"options": {
"timeout": 10000
}
},
"id": "c3d4e5f6-0007-4a5b-9c0d-333333333307",
"name": "Telegram \u2014 Send Error Alert",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1680,
260
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.PROXY_CONTROLLER_WEBHOOK }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify($json.switch_config) }}",
"options": {}
},
"id": "c3d4e5f6-0008-4a5b-9c0d-333333333308",
"name": "HTTP \u2014 Apply Proxy Switch",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1680,
400
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "python",
"pythonCode": "items = _input.all()\nhealthy = [i.json for i in items if i.json.get('is_healthy')]\nunhealthy = [i.json for i in items if not i.json.get('is_healthy')]\n\nreturn [{\n 'json': {\n 'heartbeat_summary': {\n 'total_endpoints': len(items),\n 'healthy_count': len(healthy),\n 'unhealthy_count': len(unhealthy),\n 'healthy_endpoints': [h['endpoint_name'] for h in healthy],\n 'unhealthy_endpoints': [u['endpoint_name'] for u in unhealthy],\n 'checked_at': items[0].json.get('checked_at', '') if items else ''\n }\n }\n}]"
},
"id": "c3d4e5f6-0009-4a5b-9c0d-333333333309",
"name": "Python \u2014 Build Heartbeat Summary",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1440,
520
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "all-healthy",
"leftValue": "={{ $json.heartbeat_summary.unhealthy_count }}",
"rightValue": 0,
"operator": {
"type": "number",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "c3d4e5f6-0010-4a5b-9c0d-333333333310",
"name": "IF \u2014 All Healthy?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1680,
520
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.HEALTH_LOG_WEBHOOK }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify($json.heartbeat_summary) }}",
"options": {}
},
"id": "c3d4e5f6-0011-4a5b-9c0d-333333333311",
"name": "HTTP \u2014 Log Healthy Status",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1920,
520
]
}
],
"connections": {
"Schedule \u2014 Every 5 Minutes": {
"main": [
[
{
"node": "Python \u2014 Load Tunnel Registry",
"type": "main",
"index": 0
}
]
]
},
"Python \u2014 Load Tunnel Registry": {
"main": [
[
{
"node": "HTTP \u2014 Ping Endpoint",
"type": "main",
"index": 0
}
]
]
},
"HTTP \u2014 Ping Endpoint": {
"main": [
[
{
"node": "Python \u2014 Evaluate Health Status",
"type": "main",
"index": 0
}
]
]
},
"Python \u2014 Evaluate Health Status": {
"main": [
[
{
"node": "IF \u2014 status_code != 200?",
"type": "main",
"index": 0
},
{
"node": "Python \u2014 Build Heartbeat Summary",
"type": "main",
"index": 0
}
]
]
},
"IF \u2014 status_code != 200?": {
"main": [
[
{
"node": "Python \u2014 Switch to Fallback Proxy",
"type": "main",
"index": 0
}
],
[]
]
},
"Python \u2014 Switch to Fallback Proxy": {
"main": [
[
{
"node": "Telegram \u2014 Send Error Alert",
"type": "main",
"index": 0
},
{
"node": "HTTP \u2014 Apply Proxy Switch",
"type": "main",
"index": 0
}
]
]
},
"Python \u2014 Build Heartbeat Summary": {
"main": [
[
{
"node": "IF \u2014 All Healthy?",
"type": "main",
"index": 0
}
]
]
},
"IF \u2014 All Healthy?": {
"main": [
[
{
"node": "HTTP \u2014 Log Healthy Status",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": ""
},
"staticData": null,
"tags": [
{
"name": "network-monitoring",
"createdAt": "2026-06-08T00:00:00.000Z",
"updatedAt": "2026-06-08T00:00:00.000Z",
"id": "tag-network"
},
{
"name": "hysteria2",
"createdAt": "2026-06-08T00:00:00.000Z",
"updatedAt": "2026-06-08T00:00:00.000Z",
"id": "tag-hy2"
},
{
"name": "telegram-alerts",
"createdAt": "2026-06-08T00:00:00.000Z",
"updatedAt": "2026-06-08T00:00:00.000Z",
"id": "tag-telegram"
}
],
"triggerCount": 1,
"updatedAt": "2026-06-08T12:00:00.000Z",
"versionId": "wf3-v1.0.0",
"meta": {
"templateCredsSetupCompleted": false
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Proxy Tunnel Heartbeat — Hysteria2 / Residential Monitor + Telegram Alerts. Uses httpRequest. Scheduled trigger; 11 nodes.
Source: https://github.com/36412749-collab/n8n-ai-agent-scraping-booster/blob/main/n8n_workflow_3_proxy_tunnel_heartbeat.json — 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.
Template 14310. Uses httpRequest, stopAndError, slack, gmail. Scheduled trigger; 53 nodes.
🧑🏾 Chief of Staff — System Intelligence & Operations. Uses httpRequest, microsoftOutlook. Scheduled trigger; 52 nodes.
Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 46 nodes.
Reputation Engine — Content Research Agent. Uses httpRequest. Scheduled trigger; 45 nodes.
Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 44 nodes.