This workflow corresponds to n8n.io template #6123 — 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": "y14U747S0lkSySQU",
"name": "Real-Time Currency Conversion via Webhook & Google Search Parsing",
"tags": [],
"nodes": [
{
"id": "01c90132-d787-4395-b05d-e8eaebf2a752",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-380,
140
],
"parameters": {
"path": "currency-converter",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 1
},
{
"id": "dbabc742-99b5-4a9d-8d45-7550507b1430",
"name": "Check Query Parameter",
"type": "n8n-nodes-base.if",
"position": [
-160,
140
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition1",
"operator": {
"type": "string",
"operation": "exists"
},
"leftValue": "={{ $json.query.q }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "a3121bd1-daec-423a-b8aa-a7907ff23c80",
"name": "Fetch Exchange Rate",
"type": "n8n-nodes-base.httpRequest",
"position": [
80,
60
],
"parameters": {
"url": "=https://www.google.com/search?q={{ encodeURIComponent($json.query.q) }}+exchange+rate",
"options": {}
},
"typeVersion": 4.1
},
{
"id": "31cb6085-08cf-492c-834f-e8c48c6dc2aa",
"name": "Extract Conversion Data",
"type": "n8n-nodes-base.code",
"position": [
300,
60
],
"parameters": {
"jsCode": "// Extract conversion data from Google search results\nconst htmlContent = $input.first().json.data;\nconst query = $('Webhook').first().json.query.q;\n\n// Parse the query to extract amount, from currency, and to currency\nconst queryMatch = query.match(/(\\d+(?:\\.\\d+)?)\\s*([a-zA-Z]{3})\\s+to\\s+([a-zA-Z]{3})/i);\n\nif (!queryMatch) {\n return [{\n json: {\n error: 'Invalid query format. Please use format like: 5usd to mxn',\n originalQuery: query\n }\n }];\n}\n\nconst amount = parseFloat(queryMatch[1]);\nconst fromCurrency = queryMatch[2].toUpperCase();\nconst toCurrency = queryMatch[3].toUpperCase();\n\n// Try to extract exchange rate from various possible selectors\nlet exchangeRate = null;\nlet convertedAmount = null;\n\n// Common patterns in Google search results\nconst patterns = [\n // Pattern 1: Direct rate extraction\n /([0-9,.]+)\\s*([A-Z]{3})\\s*=\\s*([0-9,.]+)\\s*([A-Z]{3})/g,\n // Pattern 2: Rate in format \"1 USD = X MXN\"\n /1\\s*([A-Z]{3})\\s*=\\s*([0-9,.]+)\\s*([A-Z]{3})/g,\n // Pattern 3: Direct conversion result\n new RegExp(`${amount}\\\\s*${fromCurrency}\\\\s*=\\\\s*([0-9,.]+)\\\\s*${toCurrency}`, 'i')\n];\n\n// Try to find exchange rate information\nfor (const pattern of patterns) {\n const matches = [...htmlContent.matchAll(pattern)];\n if (matches.length > 0) {\n const match = matches[0];\n if (pattern === patterns[2]) {\n // Direct conversion result\n convertedAmount = parseFloat(match[1].replace(/,/g, ''));\n exchangeRate = convertedAmount / amount;\n break;\n } else {\n // Extract rate from other patterns\n const rateValue = parseFloat(match[2].replace(/,/g, ''));\n if (match[1] === fromCurrency && match[3] === toCurrency) {\n exchangeRate = rateValue;\n } else if (match[3] === fromCurrency && match[1] === toCurrency) {\n exchangeRate = 1 / rateValue;\n }\n \n if (exchangeRate) {\n convertedAmount = amount * exchangeRate;\n break;\n }\n }\n }\n}\n\n// Fallback: Try to find any number that could be the conversion result\nif (!convertedAmount) {\n const numberPattern = new RegExp(`${amount}[^0-9]*([0-9,.]+)`, 'g');\n const numberMatches = [...htmlContent.matchAll(numberPattern)];\n \n if (numberMatches.length > 0) {\n convertedAmount = parseFloat(numberMatches[0][1].replace(/,/g, ''));\n exchangeRate = convertedAmount / amount;\n }\n}\n\n// If still no result, provide a fallback\nif (!convertedAmount) {\n return [{\n json: {\n error: 'Could not extract exchange rate from search results',\n originalQuery: query,\n suggestion: 'Please try a different currency pair or check the format'\n }\n }];\n}\n\nreturn [{\n json: {\n originalQuery: query,\n amount: amount,\n fromCurrency: fromCurrency,\n toCurrency: toCurrency,\n exchangeRate: exchangeRate,\n convertedAmount: convertedAmount,\n timestamp: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
},
{
"id": "bd26c221-e72c-480c-8263-fc7b53c32ab5",
"name": "Format Currency Response",
"type": "n8n-nodes-base.code",
"position": [
520,
60
],
"parameters": {
"jsCode": "// Format the currency response\nconst data = $input.first().json;\n\nif (data.error) {\n return [{\n json: {\n response: `Error: ${data.error}`,\n statusCode: 400\n }\n }];\n}\n\n// Format the conversion result\nconst formattedResult = `${data.amount} ${data.fromCurrency} = ${data.convertedAmount.toFixed(2)} ${data.toCurrency}`;\n\n// Additional metadata\nconst responseData = {\n result: formattedResult,\n details: {\n amount: data.amount,\n fromCurrency: data.fromCurrency,\n toCurrency: data.toCurrency,\n exchangeRate: data.exchangeRate ? data.exchangeRate.toFixed(6) : null,\n convertedAmount: data.convertedAmount.toFixed(2),\n timestamp: data.timestamp\n },\n query: data.originalQuery\n};\n\nreturn [{\n json: {\n response: formattedResult,\n data: responseData,\n statusCode: 200\n }\n}];"
},
"typeVersion": 2
},
{
"id": "4a7f148a-f01a-4f26-98d2-2e058341330f",
"name": "Send Conversion Response",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
740,
60
],
"parameters": {
"options": {
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"respondWith": "json",
"responseBody": "={{ $json.response }}"
},
"typeVersion": 1
},
{
"id": "37a7bae1-7c0c-4a72-9550-3d7c6c67a5f9",
"name": "Error Response",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
100,
380
],
"parameters": {
"options": {
"responseCode": 400,
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"respondWith": "json",
"responseBody": "{ \"error\": \"Missing query parameter 'q'. Please use format: ?q=5usd+to+mxn\" }"
},
"typeVersion": 1
},
{
"id": "b5b660a8-0130-4f03-b342-f7cde6a953e7",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
0
],
"parameters": {
"width": 160,
"height": 300,
"content": "Captures GET requests with query parameter q"
},
"typeVersion": 1
},
{
"id": "cae401d6-8d37-4683-83f5-6eec4c22b80d",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
60,
-80
],
"parameters": {
"color": 4,
"width": 160,
"height": 300,
"content": "Makes HTTP request to Google search for exchange rates"
},
"typeVersion": 1
},
{
"id": "e2df2060-b940-440f-8fa7-1959dc8d2108",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
280,
-80
],
"parameters": {
"width": 160,
"height": 300,
"content": "Processes HTML response to extract conversion data"
},
"typeVersion": 1
},
{
"id": "7440d55d-141b-45a5-b48d-af9645d8d1a2",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
500,
-80
],
"parameters": {
"color": 5,
"width": 160,
"height": 300,
"content": "Formats the result into a user-friendly response"
},
"typeVersion": 1
},
{
"id": "edcf84b9-6d25-424a-9ced-6beedee0ae57",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
720,
-80
],
"parameters": {
"color": 3,
"width": 160,
"height": 300,
"content": "Returns the formatted response"
},
"typeVersion": 1
},
{
"id": "0a5d4fc0-16ff-4555-bca1-03935131f37c",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-180,
0
],
"parameters": {
"color": 3,
"width": 160,
"height": 300,
"content": "Validates that the required query parameter exists"
},
"typeVersion": 1
},
{
"id": "3c747ff3-a353-4793-9a20-76e4da4b1cc2",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
60,
240
],
"parameters": {
"color": 6,
"width": 160,
"height": 300,
"content": "Handles missing query parameter errors"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "306ff349-278a-4f2e-b837-cc7213eb0f99",
"connections": {
"Webhook": {
"main": [
[
{
"node": "Check Query Parameter",
"type": "main",
"index": 0
}
]
]
},
"Fetch Exchange Rate": {
"main": [
[
{
"node": "Extract Conversion Data",
"type": "main",
"index": 0
}
]
]
},
"Check Query Parameter": {
"main": [
[
{
"node": "Fetch Exchange Rate",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Response",
"type": "main",
"index": 0
}
]
]
},
"Extract Conversion Data": {
"main": [
[
{
"node": "Format Currency Response",
"type": "main",
"index": 0
}
]
]
},
"Format Currency Response": {
"main": [
[
{
"node": "Send Conversion Response",
"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 automated n8n workflow provides real-time currency conversion by capturing GET requests via a webhook, parsing exchange rate data from Google Search, and returning a formatted response. The system handles query parameter validation and error cases to ensure reliable…
Source: https://n8n.io/workflows/6123/ — 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 n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di
This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .
This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c
Sign PDF documents with legally-compliant digital signatures using X.509 certificates. Supports multiple PAdES signature levels (B, T, LT, LTA) with optional visible stamps.
📡 This workflow serves as the central Alpha Vantage API fetcher for Tesla trading indicators, delivering cleaned 20-point JSON outputs for three timeframes: , , and . It is required by the following a