AutomationFlowsWeb Scraping › Image to Anki Deck (apkg)

Image to Anki Deck (apkg)

Image to Anki Deck (APKG). Uses httpRequest. Webhook trigger; 7 nodes.

Webhook trigger★★★★☆ complexity7 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 7 Complexity: ★★★★☆ Added:

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": "image-to-anki",
  "name": "Image to Anki Deck (APKG)",
  "nodes": [
    {
      "id": "webhook-trigger",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        100,
        300
      ],
      "parameters": {
        "path": "image-to-anki",
        "httpMethod": "POST",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "normalize-input",
      "name": "Normalize Input",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        300,
        300
      ],
      "parameters": {
        "jsCode": "// Normalize and validate input - returns error JSON if invalid\nconst body = $input.first().json.body || {};\nconst deckName = (body.deckName && typeof body.deckName === 'string') ? body.deckName.trim() : 'Vocabulary';\n// Audio is ON by default (opt-out, not opt-in)\nconst includeAudio = body.includeAudio !== false;\nconst mode = (body.mode === 'suffix') ? 'suffix' : 'vocabulary';\n\nif (body.imageUrl && typeof body.imageUrl === 'string' && body.imageUrl.length > 0) {\n  return [{ json: { ...($input.first().json), imageSource: body.imageUrl, inputType: 'url', isValid: true, base64Only: null, deckName, includeAudio, mode } }];\n}\n\nif (body.imageData && typeof body.imageData === 'string' && body.imageData.length > 0) {\n  let data = body.imageData;\n  if (!data.startsWith('data:')) {\n    data = 'data:image/png;base64,' + data;\n  }\n  const base64Only = data.split('base64,')[1] || null;\n  return [{ json: { ...($input.first().json), imageSource: data, inputType: 'base64', isValid: true, base64Only, deckName, includeAudio, mode } }];\n}\n\nreturn [{ json: { isValid: false, error: 'Missing image. Send POST with {\"imageUrl\": \"...\"} or {\"imageData\": \"...\"}' } }];\n"
      }
    },
    {
      "id": "check-valid",
      "name": "Check Valid",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        500,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "is-valid",
              "leftValue": "={{ $json.isValid }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "error-response",
      "name": "Error Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        700,
        500
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: false, error: $json.error }) }}",
        "options": {
          "responseCode": 400
        }
      }
    },
    {
      "id": "create-job",
      "name": "Create Job",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        700,
        300
      ],
      "parameters": {
        "jsCode": "const fs = require('fs');\nconst path = require('path');\nconst crypto = require('crypto');\n\nconst item = $input.first().json;\nconst jobId = crypto.randomUUID();\nconst jobDir = path.join('/var/lib/n8n/jobs', jobId);\nconst includeAudio = item.includeAudio !== false;\nconst mode = (item.mode === 'suffix') ? 'suffix' : 'vocabulary';\n\n// Create job directory\nfs.mkdirSync(jobDir, { recursive: true });\n\n// Write initial status\nconst status = {\n  status: 'queued',\n  phase: 'Job queued, starting processing...',\n  progress: 0,\n  wordCount: null,\n  currentWord: null,\n  includeAudio,\n  mode,\n  createdAt: new Date().toISOString()\n};\nfs.writeFileSync(path.join(jobDir, 'status.json'), JSON.stringify(status, null, 2));\n\n// Build status URL\nconst host = item.headers?.host || 'localhost:5678';\nconst protocol = host.includes('ts.net') ? 'https' : 'http';\nconst statusUrl = `${protocol}://${host}/webhook/anki-status?id=${jobId}`;\nconst deckName = item.deckName || 'Vocabulary';\n\nreturn [{ json: { jobId, jobDir, statusUrl, imageSource: item.imageSource, deckName, includeAudio, mode, host } }];\n"
      }
    },
    {
      "id": "trigger-worker",
      "name": "Trigger Worker",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        900,
        300
      ],
      "continueOnFail": true,
      "parameters": {
        "method": "POST",
        "url": "=http://127.0.0.1:5678/webhook/anki-worker",
        "authentication": "none",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ jobId: $json.jobId, imageSource: $json.imageSource, deckName: $json.deckName, includeAudio: $json.includeAudio, mode: $json.mode }) }}",
        "options": {
          "timeout": 1000
        }
      }
    },
    {
      "id": "accepted-response",
      "name": "Accepted Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1100,
        300
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, status: 'processing', jobId: $('Create Job').first().json.jobId, statusUrl: $('Create Job').first().json.statusUrl, message: 'Job accepted. Poll statusUrl for progress.' }) }}",
        "options": {
          "responseCode": 202
        }
      }
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Normalize Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Input": {
      "main": [
        [
          {
            "node": "Check Valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Valid": {
      "main": [
        [
          {
            "node": "Create Job",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Error Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Job": {
      "main": [
        [
          {
            "node": "Trigger Worker",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Worker": {
      "main": [
        [
          {
            "node": "Accepted Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": true,
  "versionId": "28701dde-acfd-460c-a39f-fdd4d9660115"
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Image to Anki Deck (APKG). Uses httpRequest. Webhook trigger; 7 nodes.

Source: https://github.com/alexandru-savinov/nixos-config/blob/abbfe975654bcfa221398b95aca49c1e36758e6e/n8n-workflows/image-to-anki.json — 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