AutomationFlowsData & Sheets › Generate & Upload Images with Image-to-image Gpt, Google Sheets & Drive

Generate & Upload Images with Image-to-image Gpt, Google Sheets & Drive

ByEvoort Solutions @evoortsolutions on n8n.io

Automatically generate AI images from prompts listed in a Google Sheet, upload the images to Google Drive, and log the result back into the sheet.

Event trigger★★★★☆ complexity23 nodesGoogle SheetsGoogle DriveHTTP Request
Data & Sheets Trigger: Event Nodes: 23 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #6215 — we link there as the canonical source.

This workflow follows the Google Drive → Google Sheets recipe pattern — see all workflows that pair these two integrations.

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
{
  "nodes": [
    {
      "id": "1f995205-641d-4a03-a6d4-aada6bb2cb17",
      "name": "Google Sheets2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -480,
        260
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "36bdf920-27c4-4fb8-9f83-468e8d66a699",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -240,
        260
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "886a068d-0e1b-40a9-a4f9-5a8cd51ec90c",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        2000,
        540
      ],
      "parameters": {
        "amount": 10
      },
      "typeVersion": 1.1
    },
    {
      "id": "5f9b58bc-228e-4cf2-ba1d-76fde79e8af8",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -760,
        260
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "a46bc160-9ea7-4834-a031-b5b025f5356c",
      "name": "If2",
      "type": "n8n-nodes-base.if",
      "position": [
        20,
        280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e0b7b7c8-3a7a-466d-bae7-269282b49d34",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.Prompt }}",
              "rightValue": ""
            },
            {
              "id": "64dde394-0e49-4306-a24a-de2bf448fc95",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json['drive path'] }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8a87ab83-d243-41f3-b85f-a0cbbb1edee2",
      "name": "If1",
      "type": "n8n-nodes-base.if",
      "position": [
        560,
        360
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "205d9270-aa0e-4864-bbb6-c67206eda0a2",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.error }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d162216f-c4bb-4f6b-a116-15d3cd986b7c",
      "name": "Google Sheets4",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1260,
        560
      ],
      "parameters": {
        "columns": {
          "value": {
            "Base64": "={{ $json.error }}",
            "Prompt": "={{ $json.Prompt }}"
          },
          "schema": [
            {
              "id": "Prompt",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "drive path",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "drive path",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Generated Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Generated Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Base64",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Base64",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Prompt"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "84fbc87b-3511-4945-97b2-254bd644bed3",
      "name": "Google Sheets1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        940,
        260
      ],
      "parameters": {
        "columns": {
          "value": {
            "Base64": "={{ $('HTTP Request1').item.json.image_base64 }}",
            "Prompt": "={{ $('If2').item.json.Prompt }}",
            "Generated Date": "={{$now}}"
          },
          "schema": [
            {
              "id": "Prompt",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "drive path",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "drive path",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Generated Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Generated Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Base64",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Base64",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "7a7b4988-9650-48c5-a9cc-339a9403f090",
      "name": "Google Drive1",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        860,
        -100
      ],
      "parameters": {
        "name": "={{ $binary.data.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "4d7b5ebe-2df9-4ac2-9b38-5e709654514d",
      "name": "HTTP Request1",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        240,
        240
      ],
      "parameters": {
        "url": "https://image-to-image-gpt.p.rapidapi.com/productgpt/index.php",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "multipart-form-data",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "prompt",
              "value": "={{ $json.Prompt }}"
            },
            {
              "name": "image",
              "value": "={{ $json['Image url'] }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "x-rapidapi-host",
              "value": "image-to-image-gpt.p.rapidapi.com"
            },
            {
              "name": "x-rapidapi-key",
              "value": "your key"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "abc66cee-05b8-4bb7-976b-55130b761fda",
      "name": "Code1",
      "type": "n8n-nodes-base.code",
      "position": [
        540,
        -100
      ],
      "parameters": {
        "jsCode": "const base64String = $input.first().json.image_base64;\nconsole.log(base64String);\n// If it includes a prefix like 'data:image/jpeg;base64,', split it\nconst cleanedBase64 = base64String.includes(\",\")\n  ? base64String.split(\",\")[1]\n  : base64String;\n\nreturn [\n  {\n    binary: {\n      data: {\n        data: Buffer.from(cleanedBase64, 'base64'),\n        mimeType: 'image/jpeg', // or image/png depending on the format\n        fileName: 'output.jpg'\n      }\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d268cfe7-3ca2-4d96-9965-263fb1d8146a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1780,
        -380
      ],
      "parameters": {
        "width": 720,
        "height": 1280,
        "content": "# \ud83e\udde0 AI Image Generator with Google Sheets & Drive\n\n## \ud83d\udccc Purpose\nAutomatically generate images from prompts in Google Sheets, upload them to Google Drive, and log the link back to the sheet.\n\n---\n\n## \u2705 Key Benefits\n- Zero manual effort to generate/store images\n- Centralized prompt management via Google Sheets\n- Drive integration provides shareable image links\n- Built-in error handling and logging\n\n---\n\n## \ud83e\udde9 Node Descriptions (One-liners)\n\n**1. Manual Trigger**  \nStarts the flow when you manually execute the workflow.\n\n**2. Google Sheets2**  \nReads rows (prompts) from the connected Google Sheet.\n\n**3. Loop Over Items**  \nIterates over each row from the sheet.\n\n**4. If2**  \nFilters rows: continues only if a prompt exists and no image is yet uploaded.\n\n**5. HTTP Request**  \nSends the prompt to the AI image generation API (e.g., RapidAPI).\n\n**6. Try Catch**  \nHandles any API or logic errors gracefully.\n\n**7. Google Drive**  \nUploads the generated base64 image to Google Drive.\n\n**8. Set**  \nConstructs a public share URL for the uploaded image.\n\n**9. Google Sheets1**  \nUpdates the original sheet row with the Drive image link.\n\n**10. Google Sheets3 (Logger)**  \nWrites success/failure logs to a separate sheet or tab.\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "61abe854-c306-488c-b427-bfd51b88cde1",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -840,
        120
      ],
      "parameters": {
        "height": 280,
        "content": "### 1. **Manual Trigger**\nManually starts the workflow for testing or controlled execution."
      },
      "typeVersion": 1
    },
    {
      "id": "1e81a32e-5e79-4b20-8067-0258d068f874",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        80
      ],
      "parameters": {
        "height": 340,
        "content": "### 2. **Google Sheets2 \u2013 Fetch Prompts**\n- Connects to a specific Google Sheet.\n- Reads rows that include prompts.\n- These prompts will be used to generate images."
      },
      "typeVersion": 1
    },
    {
      "id": "880542b2-bf17-48ad-951e-466073fc0008",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -300,
        100
      ],
      "parameters": {
        "width": 220,
        "height": 280,
        "content": "### 3. **Loop Over Items**\n- Loops through each row one by one.\n- This ensures each prompt is handled independently.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "27299667-dba0-4ea4-99d3-1ccaac9342bc",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        40
      ],
      "parameters": {
        "width": 220,
        "height": 360,
        "content": "### 4. **If2 \u2013 Filter Valid Rows**\n- Checks two conditions:\n  1. Whether the \"Prompt\" column has text\n  2. Whether the \"drive path\" column is empty (i.e., not processed yet)\n- If both conditions pass, the flow proceeds; otherwise, it skips to the next row.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "23efdf34-796a-41b7-9b32-ef18e0ce408f",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        200,
        20
      ],
      "parameters": {
        "height": 340,
        "content": "### 5. **HTTP Request \u2013 Call Image API**\n- Sends a POST or GET request to the AI image generator API (like RapidAPI or Replicate).\n- Includes the prompt as a parameter.\n- Receives the image in base64 or URL form.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c8555a0b-fd48-4776-bb95-f9148fbaaaa5",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        180
      ],
      "parameters": {
        "height": 300,
        "content": "### 6. **Try Catch \u2013 Error Handling**\n- Wraps around the API call and upload step.\n- If image generation or upload fails, the error is caught here and handled without breaking the loop."
      },
      "typeVersion": 1
    },
    {
      "id": "d5c01bf8-aa58-4dd3-a066-96c177e723bf",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        500,
        -320
      ],
      "parameters": {
        "height": 380,
        "content": "### 7. **Google Drive \u2013 Upload Image**\n- Converts base64 image (if needed).\n- Uploads the image to a specified Google Drive folder.\n- Retrieves the public/shared URL of the uploaded image.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1c9adb0e-e7ff-418f-ace3-6064f5ea6ea5",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        -240
      ],
      "parameters": {
        "height": 280,
        "content": "### 8. **Set \u2013 Prepare Image Link**\n- Formats the image URL from Drive to make it user-friendly or shareable.\n- Prepares this value to update back into the sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "5f0d6cd1-9c02-4883-9574-1886c7ecaad4",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        860,
        80
      ],
      "parameters": {
        "height": 320,
        "content": "### 9. **Google Sheets1 \u2013 Update Sheet**\n- Writes the image link into the same row from which the prompt came.\n- Marks the row as \"processed\" by updating the drive path field."
      },
      "typeVersion": 1
    },
    {
      "id": "b1f0dccc-5124-4d89-af0b-8cead135c300",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1180,
        360
      ],
      "parameters": {
        "height": 300,
        "content": "### 10. **Google Sheets3 \u2013 Log Status**\n- Appends a new row in a separate log sheet or tab.\n- Records status (success/failure), prompt, and time.\n- Useful for tracking flow execution over time."
      },
      "typeVersion": 1
    },
    {
      "id": "30397d7d-206e-4a64-b262-05858e226f1a",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1940,
        380
      ],
      "parameters": {
        "height": 320,
        "content": "This node is used to insert a delay before proceeding to the next step in the workflow. In your case, the node waits for `10 seconds`."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "If1": {
      "main": [
        [
          {
            "node": "Google Sheets4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If2": {
      "main": [
        [
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Google Drive1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Google Sheets1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive1": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request1": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets1": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets2": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets4": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "If2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Google Sheets2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

Automatically generate AI images from prompts listed in a Google Sheet, upload the images to Google Drive, and log the result back into the sheet.

Source: https://n8n.io/workflows/6215/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.

Google Sheets, HTTP Request, @N Octo N/N8N Nodes Json Database +3
Data & Sheets

The workflow automates the process of gathering extensive keyword data for a "Main Keyword." It starts by reading initial parameters from a Google Sheets template, creates a new dedicated Google Sheet

Google Sheets, Google Drive, HTTP Request
Data & Sheets

🔥 March Sale – n8n Community Members Get ideoGener8r for Just $27! (Reg. $47) Use Coupon Code: (Valid until 3/31/2025 for n8n community members)

HTTP Request, Google Drive, Google Sheets
Data & Sheets

📄 Documentation: Notion Guide

Google Sheets, Google Drive, HTTP Request +2
Data & Sheets

Overview

Google Sheets, Google Drive, HTTP Request