AutomationFlowsWeb Scraping › Real-time Currency Conversion via Webhook & Google Search Parsing

Real-time Currency Conversion via Webhook & Google Search Parsing

ByOneclick AI Squad @oneclick-ai on n8n.io

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…

Webhook trigger★★★★☆ complexity14 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 14 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "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
          }
        ]
      ]
    }
  }
}
Pro

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 →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

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

n8n, Execute Workflow Trigger, HTTP Request +1
Web Scraping

This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .

HTTP Request, Ssh
Web Scraping

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

HTTP Request
Web Scraping

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.

Execute Command, HTTP Request, Read Write File +1
Web Scraping

📡 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

HTTP Request