One of the most common mistakes when you start writing WordPress plugins or themes is building path strings by hand. Something like this:

// Do not do this
include '/home/user/public_html/wp-content/plugins/my-plugin/inc/helper.php';

That code works on your machine and breaks the moment it lands on a different server. WordPress ships a set of functions for getting paths, and the first thing to understand is that there are two completely different kinds of path.

Filesystem paths and URLs

A filesystem path is where the file sits on the server’s disk, for example /var/www/html/wp-content/plugins/my-plugin/. Use it when you are working with files in PHP: include, require, file_get_contents, fopen.

A URL is an address the browser can reach, for example https://example.com/wp-content/plugins/my-plugin/. Use it when you are embedding assets into a page: CSS, JavaScript, images.

Mixing these two up causes a lot of confusing bugs. Put a filesystem path in an <img> tag and the image never loads. include a URL and you either get an error or open a serious security hole.

Quick reference

FunctionReturnsExample result
ABSPATHWordPress root path/var/www/html/
plugin_dir_path( __FILE__ )Path to the current plugin directory/var/www/html/wp-content/plugins/my-plugin/
plugin_dir_url( __FILE__ )URL of the current plugin directoryhttps://example.com/wp-content/plugins/my-plugin/
plugins_url()URL of the /plugins directoryhttps://example.com/wp-content/plugins
get_template_directory()Parent theme path/var/www/html/wp-content/themes/parent/
get_stylesheet_directory()Active theme path (child if there is one)/var/www/html/wp-content/themes/child/
get_stylesheet_directory_uri()Active theme URLhttps://example.com/wp-content/themes/child
content_url()URL of /wp-contenthttps://example.com/wp-content
includes_url()URL of /wp-includeshttps://example.com/wp-includes
admin_url()URL of the admin areahttps://example.com/wp-admin/
site_url()URL where WordPress is installedhttps://example.com
home_url()URL of the home pagehttps://example.com
wp_upload_dir()Array with both path and URL for uploadssee below

In a plugin

In the main plugin file, the standard approach is to define constants once and reuse them:

<?php
define( 'MY_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
define( 'MY_PLUGIN_URL',  plugin_dir_url( __FILE__ ) );

// Loading PHP files: use PATH
require_once MY_PLUGIN_PATH . 'includes/class-loader.php';

// Enqueuing assets: use URL
function my_plugin_assets() {
    wp_enqueue_style( 'my-plugin', MY_PLUGIN_URL . 'assets/style.css', [], '1.0.0' );
    wp_enqueue_script( 'my-plugin', MY_PLUGIN_URL . 'assets/app.js', [ 'jquery' ], '1.0.0', true );
}
add_action( 'wp_enqueue_scripts', 'my_plugin_assets' );

__FILE__ is a PHP constant pointing at the currently executing file, so both functions give correct results no matter where the plugin is installed.

In a theme

For themes, the important thing is telling parent and child apart:

// Always points at the PARENT theme, even when a child theme is active
get_template_directory();
get_template_directory_uri();

// Points at the ACTIVE theme (child if there is one, otherwise the parent)
get_stylesheet_directory();
get_stylesheet_directory_uri();

The practical rule: when you are writing code in a child theme and want to reference the child theme’s own files, use get_stylesheet_directory(). When you want to reference the parent theme’s files, use get_template_directory().

The uploads directory

wp_upload_dir() returns an array rather than a string:

$upload = wp_upload_dir();

echo $upload['basedir']; // /var/www/html/wp-content/uploads
echo $upload['baseurl']; // https://example.com/wp-content/uploads
echo $upload['path'];    // .../uploads/2026/09  (current month's folder)
echo $upload['url'];     // .../uploads/2026/09

Never assume the uploads directory is at wp-content/uploads, because it can be moved through configuration.

site_url() or home_url()

These two usually return the same value, which is why people mix them up. They only differ when WordPress is installed in a subdirectory but the site runs at the root domain:

  • site_url() returns https://example.com/wordpress (where the code lives)
  • home_url() returns https://example.com (the address visitors see)

The rule: for links shown to visitors use home_url(), and for pointing at WordPress core files use site_url().

One note on escaping

None of the URL functions escape their output. When you print them into HTML, wrap them:

<img src="<?php echo esc_url( MY_PLUGIN_URL . 'assets/logo.png' ); ?>" alt="Logo">