4.6.x common.inc drupal_goto($path = '', $query = NULL, $fragment = NULL)
4.7.x common.inc drupal_goto($path = '', $query = NULL, $fragment = NULL)
5.x common.inc drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302)
6.x common.inc drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302)
7.x common.inc drupal_goto($path = '', array $options = array(), $http_response_code = 302)

Send the user to a different Drupal page.

This issues an on-site HTTP redirect. The function makes sure the redirected URL is formatted correctly.

Usually the redirected URL is constructed from this function's input parameters. However you may override that behavior by setting a destination in either the $_REQUEST-array (i.e. by using the query string of an URI) or the $_REQUEST['edit']-array (i.e. by using a hidden form field). This is used to direct the user back to the proper page after completing a form. For example, after editing a post on the 'admin/content/node'-page or after having logged on using the 'user login'-block in a sidebar. The function drupal_get_destination() can be used to help set the destination URL.

Drupal will ensure that messages set by drupal_set_message() and other session data are written to the database before the user is redirected.

This function ends the request; use it rather than a print theme('page') statement in your menu callback.


$path: (optional) A Drupal path or a full URL, which will be passed to url() to compute the redirect for the URL.

$query: (optional) A URL-encoded query string to append to the link, or an array of query key/value-pairs without any URL-encoding. Passed to url().

$fragment: (optional) A destination fragment identifier (named anchor).

$http_response_code: (optional) The HTTP status code to use for the redirection, defaults to 302. The valid values for 3xx redirection status codes are defined in RFC 2616 and the draft for the new HTTP status codes:

  • 301: Moved Permanently (the recommended value for most redirects).
  • 302: Found (default in Drupal and PHP, sometimes used for spamming search engines).
  • 303: See Other.
  • 304: Not Modified.
  • 305: Use Proxy.
  • 307: Temporary Redirect.

See also


Related topics

25 calls to drupal_goto()
aggregator_admin_refresh_feed in modules/aggregator/aggregator.admin.inc
Menu callback; refreshes a feed, then redirects to the overview page.
batch_process in includes/form.inc
Processes the batch.
comment_multiple_delete_confirm in modules/comment/comment.admin.inc
List the selected comments and verify that the admin really wants to delete them.
drupal_redirect_form in includes/form.inc
Redirect the user to a URL after a form has been processed.
locale_languages_delete_form in includes/locale.inc
User interface for the language deletion confirmation screen.

... See full list

1 string reference to 'drupal_goto'
drupal_redirect_form in includes/form.inc
Redirect the user to a URL after a form has been processed.


includes/common.inc, line 332
Common functions that many Drupal modules will need to reference.


function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
  $destination = FALSE;
  if (isset($_REQUEST['destination'])) {
    $destination = $_REQUEST['destination'];
  else {
    if (isset($_REQUEST['edit']['destination'])) {
      $destination = $_REQUEST['edit']['destination'];
  if ($destination) {

    // Do not redirect to an absolute URL originating from user input.
    if (!menu_path_is_external($destination)) {
  $options = array(
    'query' => $query,
    'fragment' => $fragment,
    'absolute' => TRUE,

  // In some cases modules call drupal_goto($_GET['q']). We need to ensure that
  // such a redirect is not to an external URL.
  if ($path === $_GET['q'] && menu_path_is_external($path)) {

    // Force url() to generate a non-external URL.
    $options['external'] = FALSE;
  $url = url($path, $options);

  // Remove newlines from the URL to avoid header injection attacks.
  $url = str_replace(array(
  ), '', $url);

  // Allow modules to react to the end of the page request before redirecting.
  // We do not want this while running update.php.
  if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
    module_invoke_all('exit', $url);

  // Even though session_write_close() is registered as a shutdown function, we
  // need all session data written to the database before redirecting.
  header('Location: ' . $url, TRUE, $http_response_code);

  // The "Location" header sends a redirect status code to the HTTP daemon. In
  // some cases this can be wrong, so we make sure none of the code below the
  // drupal_goto() call gets executed upon redirection.


drupalshrek’s picture

Imagine you want to go to the following URL:

This should be written with the 2 parameters $path and $query:

drupal_goto("my_page", "sex=1&country=BE");

which will correctly go to the required page.

Make sure that you don't try and put everything directly on the first drupal_goto parameter. The following will NOT work correctly:


since this will encode the "?" and the "=" signs as follows:

dhanesh.haridas’s picture

Query string can be used with drupal_goto() , to pass query variables with URL

Suppose we need to redirect to following URL :


  $query = array('category' => 'newcategory','country'=>'india');

alternatively the query string can be provided as string

  $query = 'category=newcategory&country=india';
NancyDru’s picture

If you provide a string, it should use drupal_urlencode() on the string. Arrays will be encoded automatically.

jakew’s picture

What's the module that allows admins to see where a drupal_goto() would land before actually going there? I can't remember its name.

Michelle’s picture

I know there's an option in there that will stop you in the middle of a redirect.


anonymous07’s picture

Yes, it can show you where you will go before taking you there so you have to option to abort; it can be very useful for testing.

Display redirection page
"When a module executes drupal_goto(), the query log and other developer information is lost. Enabling this setting presents an intermediate page to developers so that the log can be examined before continuing to the destination page."

kenorb’s picture

How to force Drupal to redirect if it doesn't work

Try as well:
before drupal_goto() if doesn't work.

jasonawant’s picture


I know this is quite old, but I thought I'd post anyway. I found this method to work.

I found the rules module uses this same method in the action 'Page Redirect' with the force option.

See rules_action_drupal_goto().


jienckebd’s picture

Not sure if this is a D7 thing, but the below worked for me:

if (isset($_GET['destination'])) {

justintime’s picture

If you use drupal_goto() in your custom module's hook_nodeapi(), it will work, but the redirect will happen before other modules get their hook_nodeapi() called, breaking other modules. Instead, use hook_form_alter() on the delete confirm form to add a redirect there.

sai01919’s picture

How to pass field values of a form to next page and how to use them in next page with GET or POST method.After form submission iam redirecting it to next page.
I need to pass field values to next page.Plz anyone kindly help me.

infojunkie’s picture

I've been trying to convince drupal_goto to redirect from an Arabic page (prefixed with ar/) to an English page (without prefix) but I keep failing. Any idea how to do that?

Anclywen’s picture

Change global variable $language from arabic to english

  global $language;
  $languages = language_list();
  $language = $languages['en'];
rayvan’s picture

I ran into a small conundrum where I had to use an internal alias path out of an internal absolute path to use in conjunction with a drupal_goto.

The use case was that the destination was from another drupal_goto, so it couldn't really be reliably used after an additional drupal_goto().

So here is what I used to grab the local alias out of the absolute path to feed into the additional goto:

    global $base_root, $base_path;
    $full_base = $base_root . $base_path;
    $referral_url = strpos($_SERVER['HTTP_REFERER'], 'yourdomain.com') !== FALSE ? $_SERVER['HTTP_REFERER'] : $full_base . 'home';
    $referral_url = str_replace($full_base, '', $referral_url);

Hope this helps someone else.

CarlHinton’s picture

When using drupal_goto you get all the query data in the URL after the ?. It would be really good if this were hidden from the user. Is there a way to do this?

CarlHinton’s picture

//url-ify the data for the POST
foreach($fields as $key=>$value) {
  $fields_string .= $key.'='.$value.'&';

//open connection

$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_MAXREDIRS, 255);

//execute post
$result = curl_exec($ch);

//close connection
perusio’s picture

According to the IETF draft on the 308 status code the 307 code differs from the 302 in the sense that the HTTP method must not be changed. I fail to see the relationship with a 503. Can someone elaborate if that's not the case please? Thanks.