---
title: "Workflow to n8n Workflow to Ai Stock Image Metadata Generator"
platform: "Promptally"
canonical_url: "https://app.promptally.dev/p/workflow-n8n-workflow-to-ai-stock-image-metadata-generator"
modality: "WORKFLOW"
category: "n8n Automation Blueprints"
compatible_models: [Universal / Model Agnostic]
access_tier: "Free Public Artifact (No Auth Required)"
license: "MIT"
---

# Workflow to n8n Workflow to Ai Stock Image Metadata Generator

**Summary:** Workflow to n8n Workflow to Ai Stock Image Metadata Generator is a verified WORKFLOW blueprint on Promptally in n8n Automation Blueprints optimized for leading AI models. Multi-step automated node blueprint for n8n Workflow to Ai Stock Image Metadata Generator. Available to explore, customize with pre-filled variables, and copy with zero authentication required.

## Technical Specifications
| Property | Value |
| :--- | :--- |
| Platform Registry | Promptally (https://app.promptally.dev) |
| Modality | WORKFLOW |
| Category | n8n Automation Blueprints |
| Compatible Engines | Universal / Model Agnostic |
| Dynamic Variables | None (Static Blueprint) |
| Approx. Token Length | 1,826 |
| Access Tier | Free Public Artifact (No Auth Required) |
| License | MIT |

### Pre-Filled Template & Production Source

````json
{
  "name": "AI Stock Image Metadata Generator",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "stock-image-meta",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Accept either { imageUrl } or { imageBase64 } (data URL) in the webhook body\nconst raw = $('Webhook').first().json.body || $('Webhook').first().json || {};\nlet imageRef = raw.imageUrl || raw.image_url || raw.image || null;\nif (!imageRef && raw.imageBase64) {\n  // Allow raw base64 without the data: prefix - wrap it\n  imageRef = raw.imageBase64.startsWith('data:') ? raw.imageBase64 : 'data:image/jpeg;base64,' + raw.imageBase64;\n}\nif (!imageRef) {\n  throw new Error('No image provided. Send JSON with \"imageUrl\" (public URL) or \"imageBase64\" (data URL).');\n}\nreturn [{ json: { imageRef } }];\n"
      },
      "id": "parse-input-1",
      "name": "Parse Input",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build the OpenAI vision request body. Prompt: stock metadata (title, description, 20-40 keywords).\nconst imageRef = $json.imageRef;\nconst body = {\n  model: 'gpt-4o-mini',\n  messages: [\n    {\n      role: 'system',\n      content: 'You are a professional stock-photo metadata writer. You write metadata that makes images SELL on stock marketplaces (Adobe Stock, Shutterstock, Getty).'\n    },\n    {\n      role: 'user',\n      content: [\n        {\n          type: 'text',\n          text: 'Analyze this image and return ONLY raw JSON (no markdown, no code fences) with exactly these fields: {\"title\": \"compelling stock title under 12 words\", \"description\": \"2-3 sentence description with subject, setting, mood, use cases\", \"keywords\": [\"20-40 lowercase keywords\", \"comma-separated array\"]}. Keywords: mix of subject, style, concept, mood, and usage keywords a buyer would search.'\n        },\n        { type: 'image_url', image_url: { url: imageRef } }\n      ]\n    }\n  ],\n  temperature: 0.3,\n  max_tokens: 800\n};\nreturn [{ json: { requestBody: JSON.stringify(body) } }];\n"
      },
      "id": "build-request-1",
      "name": "Build Vision Request",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "authentication": "none",
        "sendHeaders": true,
        "specifyHeaders": "keypair",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_OPENAI_API_KEY"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ $json.requestBody }}",
        "options": {
          "timeout": 120000
        }
      },
      "id": "vision-llm-1",
      "name": "Vision LLM",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Parse the LLM response; tolerate code fences and whitespace\nlet content = $json.choices && $json.choices[0] && $json.choices[0].message\n  ? $json.choices[0].message.content : String($json.content || '');\ncontent = content.replace(/```json\\s*/gi, '').replace(/```/g, '').trim();\nlet meta;\ntry {\n  meta = JSON.parse(content);\n} catch (e) {\n  // Fallback: extract first {...} block\n  const m = content.match(/\\{[\\s\\S]*\\}/);\n  meta = m ? JSON.parse(m[0]) : {};\n}\nconst title = (meta.title || 'Untitled').trim();\nconst description = (meta.description || '').trim();\nconst keywords = Array.isArray(meta.keywords) ? meta.keywords.map(k => String(k).trim()).filter(Boolean) : [];\nif (!title || !description || keywords.length === 0) {\n  throw new Error('Bad LLM output: missing title/description/keywords. Got: ' + content.slice(0, 200));\n}\nreturn [{ json: { title, description, keywords, keyword_count: keywords.length } }];\n"
      },
      "id": "parse-meta-1",
      "name": "Parse Metadata",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        880,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Emit the metadata row as CSV (RFC-4180-ish quoting) + a JSON view for the response\nconst t = $json.title.replace(/\"/g, '\"\"');\nconst d = $json.description.replace(/\"/g, '\"\"');\nconst kw = $json.keywords.join('; ').replace(/\"/g, '\"\"');\nconst csvLine = `\"${t}\",\"${d}\",\"${kw}\"`;\nconst csvHeader = '\"title\",\"description\",\"keywords\"';\nreturn [{\n  json: {\n    title: $json.title,\n    description: $json.description,\n    keywords: $json.keywords,\n    keyword_count: $json.keyword_count,\n    csv_row: csvLine,\n    csv: csvHeader + '\\n' + csvLine\n  }\n}];\n"
      },
      "id": "build-csv-1",
      "name": "Build CSV Row",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1100,
        0
      ]
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "responseBody": "={{ JSON.stringify({ success: true, title: $json.title, description: $json.description, keywords: $json.keywords, keyword_count: $json.keyword_count, csv: $json.csv }) }}",
        "options": {}
      },
      "id": "respond-1",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1320,
        0
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Parse Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Input": {
      "main": [
        [
          {
            "node": "Build Vision Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Vision Request": {
      "main": [
        [
          {
            "node": "Vision LLM",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Vision LLM": {
      "main": [
        [
          {
            "node": "Parse Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Metadata": {
      "main": [
        [
          {
            "node": "Build CSV Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build CSV Row": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false
  },
  "active": false
}
````

## Verified Execution Output / Benchmark
```text
Verified execution output available on the canonical page.
```

## Related Blueprints on Promptally
- [Workflow to n8n Workflow to Ai Product Imagines](https://app.promptally.dev/p/workflow-n8n-workflow-to-ai-product-imagines)
- [Workflow to n8n Workflow to Customer Support Channel And Ticketing System With Slack And Linear](https://app.promptally.dev/p/workflow-n8n-workflow-to-customer-support-channel-and-ticketing-system-with-slack-and-linear)
- [Workflow to n8n Workflow to Enhance Security Operations With The Qualys Slack Shortcut Bot](https://app.promptally.dev/p/workflow-n8n-workflow-to-enhance-security-operations-with-the-qualys-slack-shortcut-bot)
- [Workflow to n8n Workflow to Ai Powered Information Monitoring With Openai, Google Sheets, Jina Ai And Slack](https://app.promptally.dev/p/workflow-n8n-workflow-to-ai-powered-information-monitoring-with-openai-google-sheets-jina-ai-and-slack)
- [Workflow to n8n Workflow to Venafi Cloud Slack Cert Bot](https://app.promptally.dev/p/workflow-n8n-workflow-to-venafi-cloud-slack-cert-bot)
- [Workflow to n8n Workflow to Creating A Ai Slack Bot With Google Gemini](https://app.promptally.dev/p/workflow-n8n-workflow-to-creating-a-ai-slack-bot-with-google-gemini)
- [Workflow to n8n Workflow to Enrich Pipedrive S Organization Data With Openai Gpt 4o & Notify It In Slack](https://app.promptally.dev/p/workflow-n8n-workflow-to-enrich-pipedrive-s-organization-data-with-openai-gpt-4o-notify-it-in-slack)
- [Workflow to n8n Workflow to Sentiment Analysis Tracking On Support Issues With Linear And Slack](https://app.promptally.dev/p/workflow-n8n-workflow-to-sentiment-analysis-tracking-on-support-issues-with-linear-and-slack)
