// Forms · Apps Script

Build a pre-filled form URL in Google Forms.

Use Apps Script's createResponse and withItemResponse to generate a pre-filled Google Form URL programmatically — without guessing entry ID numbers.

I want to generate a Google Form link that already has certain fields filled in, so the person who opens it only needs to review and submit.

The script

copy · paste · trigger
getPrefillUrl.gs
Apps Script
// Returns a pre-filled form URL for a given name and email.
// Run getPrefillUrl() and check the Apps Script log.
function getPrefillUrl() {
  var form = FormApp.openById('YOUR_FORM_ID');
  var items = form.getItems();
  var response = form.createResponse();

  for (var i = 0; i < items.length; i++) {
    var item = items[i];
    var title = item.getTitle();

    if (title === 'Full name') {
      response.withItemResponse(
        item.asTextItem().createResponse('Jane Doe')
      );
    } else if (title === 'Email address') {
      response.withItemResponse(
        item.asTextItem().createResponse('jane@example.com')
      );
    }
  }

  Logger.log(response.toPrefilledUrl());
}

Need a variant? Gnaw writes a custom version from one sentence — fields, triggers, edge cases handled.

Walkthrough

Why entry IDs are the wrong starting point

The UI trick — open a form in preview, fill it, copy the link, read off ?entry.12345678=value — works once, for one form, manually. The moment you rename a question or duplicate the form, those numeric IDs change silently. Apps Script gives you a cleaner path: FormItem objects that carry the ID internally, so you never touch the raw number.

The key method is toPrefilledUrl(), called on a FormResponse object. That response is never submitted; it is only a data carrier for building the URL. You get it by calling form.createResponse(), attach partial answers with withItemResponse(), and call toPrefilledUrl() at the end. The numeric entry IDs appear in the output URL automatically, derived from the item objects you already hold.

Matching items by title instead of by index

form.getItems() returns every question in order, but order is fragile. The loop in the snippet above walks every item, reads its title with getTitle(), and branches on the string. That way a reordered form still builds the right URL as long as question titles stay stable.

Before calling createResponse() on an item, you must cast it to the right subtype. A plain text question needs asTextItem(); a multiple-choice question needs asMultipleChoiceItem(); a checkbox grid needs asCheckboxGridItem(). Calling createResponse() on the base Item object throws a TypeError at runtime — I have watched this bite people who copied the item reference directly out of the loop without the cast. The form's item type is readable as item.getType(), which returns a FormApp.ItemType enum value if you want to branch programmatically rather than by title.

Sending the URL from a Sheets trigger

The common real-world use is: a row appears in a Sheet (a new client, a scheduled appointment, a batch upload), and you want to email each person a form link with their data already filled. Wire an onEdit or time-driven trigger to a function that reads the row, calls getPrefillUrl() with the row's values, and passes the result to MailApp.sendEmail().

One thing worth knowing: toPrefilledUrl() produces the /viewform?usp=pp_url&entry.xxx=yyy shape, not the edit URL. If the person clicks it and submits, a new response is created — it does not update an existing response. Pre-filling is about convenience, not editing. If you need to let someone update a prior answer, you want the edit response URL from a submitted FormResponse object, which is a different method (getEditResponseUrl()) on a different object altogether.

Want a custom version?

Describe your sheet and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

4 questions
Does toPrefilledUrl() work for dropdown and multiple-choice questions?
Yes. Cast the item with asListItem() for a dropdown or asMultipleChoiceItem() for radio, then call createResponse('Option text') with the exact option string as it appears in the form. The string must match character-for-character; a trailing space or different capitalisation produces a URL that opens with the field blank.
Can I pre-fill a checkbox question with multiple values?
Yes, but the method signature changes. item.asCheckboxItem().createResponse() accepts a string array, not a single string — pass ['Option A', 'Option C']. Passing a single string instead of an array does not throw; it silently pre-fills only one checkbox.
My form is in a different Google account. Can I still open it with FormApp.openById()?
Only if the script runs as a user who has editor access to the form. If you are running the script from a personal account and the form belongs to a Workspace domain, you will get an access exception. The script and the form must be accessible to the same executing identity.
The URL I get is very long. Is there a short-link option?
Not from the Apps Script API directly. toPrefilledUrl() always returns the full query-string URL. You can pass that URL to a URL shortener (the UrlShortener Advanced Service was deprecated; use a third-party API via UrlFetchApp if you need short links) or simply send the full URL — email clients and most messaging apps handle long URLs fine.