4.6.x common.inc url($path = NULL, $query = NULL, $fragment = NULL, $absolute = FALSE)
4.7.x common.inc url($path = NULL, $query = NULL, $fragment = NULL, $absolute = FALSE)
5.x common.inc url($path = NULL, $query = NULL, $fragment = NULL, $absolute = FALSE)
6.x common.inc url($path = NULL, $options = array())
7.x common.inc url($path = NULL, array $options = array())

Generates an internal or external URL.

When creating links in modules, consider whether l() could be a better alternative than url().


$path: (optional) The internal path or external URL being linked to, such as "node/34" or "http://example.com/foo". The default value is equivalent to passing in '<front>'. A few notes:

  • If you provide a full URL, it will be considered an external URL.
  • If you provide only the path (e.g. "node/34"), it will be considered an internal link. In this case, it should be a system URL, and it will be replaced with the alias, if one exists. Additional query arguments for internal paths must be supplied in $options['query'], not included in $path.
  • If you provide an internal path and $options['alias'] is set to TRUE, the path is assumed already to be the correct path alias, and the alias is not looked up.
  • The special string '<front>' generates a link to the site's base URL.
  • If your external URL contains a query (e.g. http://example.com/foo?a=b), then you can either URL encode the query keys and values yourself and include them in $path, or use $options['query'] to let this function URL encode them.

$options: (optional) An associative array of additional options, with the following elements:

  • 'query': A URL-encoded query string to append to the link, or an array of query key/value-pairs without any URL-encoding.
  • 'fragment': A fragment identifier (named anchor) to append to the URL. Do not include the leading '#' character.
  • 'absolute' (default FALSE): Whether to force the output to be an absolute link (beginning with http:). Useful for links that will be displayed outside the site, such as in an RSS feed.
  • 'alias' (default FALSE): Whether the given path is a URL alias already.
  • 'external': Whether the given path is an external URL.
  • 'language': An optional language object. Used to build the URL to link to and look up the proper alias for the link.
  • 'base_url': Only used internally, to modify the base URL when a language dependent URL requires so.
  • 'prefix': Only used internally, to modify the path when a language dependent URL requires so.

Return value

A string containing a URL to the given path.

95 calls to url()
aggregator_admin_settings in modules/aggregator/aggregator.admin.inc
Form builder; Configure the aggregator system.
aggregator_form_feed in modules/aggregator/aggregator.admin.inc
Form builder; Generate a form to add/edit feed sources.
aggregator_page_categories in modules/aggregator/aggregator.pages.inc
Menu callback; displays all the categories used by the aggregator.
aggregator_page_category in modules/aggregator/aggregator.pages.inc
Menu callback; displays all the items aggregated in a particular category.
aggregator_page_last in modules/aggregator/aggregator.pages.inc
Menu callback; displays the most recent items gathered from any feed.

... See full list

4 string references to 'url'
aggregator_form_feed_validate in modules/aggregator/aggregator.admin.inc
Validate aggregator_form_feed form submissions.
aggregator_schema in modules/aggregator/aggregator.install
Implementation of hook_schema().
statistics_top_referrers in modules/statistics/statistics.admin.inc
Menu callback; presents the "referrer" page.
statistics_update_6000 in modules/statistics/statistics.install
Allow longer referrers.


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


function url($path = NULL, $options = array()) {

  // Merge in defaults.
  $options += array(
    'fragment' => '',
    'query' => '',
    'absolute' => FALSE,
    'alias' => FALSE,
    'prefix' => '',
  if (!isset($options['external'])) {
    $options['external'] = menu_path_is_external($path);

  // May need language dependent rewriting if language.inc is present.
  if (function_exists('language_url_rewrite')) {
    language_url_rewrite($path, $options);
  if ($options['fragment']) {
    $options['fragment'] = '#' . $options['fragment'];
  if (is_array($options['query'])) {
    $options['query'] = drupal_query_string_encode($options['query']);
  if ($options['external']) {

    // Split off the fragment.
    if (strpos($path, '#') !== FALSE) {
      list($path, $old_fragment) = explode('#', $path, 2);
      if (isset($old_fragment) && !$options['fragment']) {
        $options['fragment'] = '#' . $old_fragment;

    // Append the query.
    if ($options['query']) {
      $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . $options['query'];

    // Reassemble.
    return $path . $options['fragment'];

  // Strip leading slashes from internal paths to prevent them becoming external
  // URLs without protocol. /example.com should not be turned into
  // //example.com.
  $path = ltrim($path, '/');
  global $base_url;
  static $script;
  if (!isset($script)) {

    // On some web servers, such as IIS, we can't omit "index.php". So, we
    // generate "index.php?q=foo" instead of "?q=foo" on anything that is not
    // Apache.
    $script = strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE ? 'index.php' : '';
  if (!isset($options['base_url'])) {

    // The base_url might be rewritten from the language rewrite in domain mode.
    $options['base_url'] = $base_url;

  // Preserve the original path before aliasing.
  $original_path = $path;

  // The special path '<front>' links to the default front page.
  if ($path == '<front>') {
    $path = '';
  elseif (!empty($path) && !$options['alias']) {
    $path = drupal_get_path_alias($path, isset($options['language']) ? $options['language']->language : '');
  if (function_exists('custom_url_rewrite_outbound')) {

    // Modules may alter outbound links by reference.
    custom_url_rewrite_outbound($path, $options, $original_path);
  $base = $options['absolute'] ? $options['base_url'] . '/' : base_path();
  $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix'];
  $path = drupal_urlencode($prefix . $path);
  if (variable_get('clean_url', '0')) {

    // With Clean URLs.
    if ($options['query']) {
      return $base . $path . '?' . $options['query'] . $options['fragment'];
    else {
      return $base . $path . $options['fragment'];
  else {

    // Without Clean URLs.
    $variables = array();
    if (!empty($path)) {
      $variables[] = 'q=' . $path;
    if (!empty($options['query'])) {
      $variables[] = $options['query'];
    if ($query = join('&', $variables)) {
      return $base . $script . '?' . $query . $options['fragment'];
    else {
      return $base . $options['fragment'];


adr_p’s picture

Do not use url() to generate JS and CSS paths. Because of this fragment:

 if (function_exists('custom_url_rewrite_outbound')) {
    // Modules may alter outbound links by reference.
    custom_url_rewrite_outbound($path, $options, $original_path);

if you call e.g.:
you'll get e.g.:
That'll happen if you have modules like i18n or Spaces enabled and configured to use path prefixes.

See: http://drupal.org/node/872340

davidshaw’s picture

anything after the ? is a variable to include in the query.


url("user/register?gids[]=$node->nid", array('absolute' => TRUE))

outputs incorrect:


url("user/register", array('query' => 'gids[]='. $node->nid,'absolute' => TRUE))

which outputs the correct:

Dave Shaw
Tribe Rising

bsandor’s picture

To me it outputs:
'user/register?gids[]=6/' which actually is wrong I say.

D6 6.22

drudrew’s picture

When you use a link or file name that has an ampersand (&), url() or l() will double-encode the ampersand to %2526. It is because of drupal_urlencode() trying to compensate for Apache's mod_rewrite's behavior. I see good intention but it's not the ideal place to accomplish this. I believe it is not the case for D7 or 8. See drupal_urlencode() for the few other cases that are double-encoded.

It is especially problematic when you use url() or l() to create a link to a static file that has an ampersand in the file name.