diff --git a/message/externallib.php b/message/externallib.php
index 77b4d309c3f..b8591ae8351 100644
--- a/message/externallib.php
+++ b/message/externallib.php
@@ -425,7 +425,7 @@ class core_message_external extends external_api {
      * @since Moodle 2.5
      */
     public static function get_contacts() {
-        global $CFG;
+        global $CFG, $PAGE;
 
         // Check if messaging is enabled.
         if (!$CFG->messaging) {
@@ -444,16 +444,11 @@ class core_message_external extends external_api {
                     'unread' => $contact->messagecount
                 );
 
-                $usercontext = context_user::instance($contact->id, IGNORE_MISSING);
-                if ($usercontext) {
-                    $newcontact['profileimageurl'] = moodle_url::make_webservice_pluginfile_url(
-                                                        $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false);
-                    $newcontact['profileimageurlsmall'] = moodle_url::make_webservice_pluginfile_url(
-                                                            $usercontext->id, 'user', 'icon', null, '/', 'f2')->out(false);
-                } else {
-                    $newcontact['profileimageurl'] = '';
-                    $newcontact['profileimageurlsmall'] = '';
-                }
+                $userpicture = new user_picture($contact);
+                $userpicture->size = 1; // Size f1.
+                $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
+                $userpicture->size = 0; // Size f2.
+                $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
 
                 $allcontacts[$mode][$key] = $newcontact;
             }
@@ -535,7 +530,7 @@ class core_message_external extends external_api {
      * @since Moodle 2.5
      */
     public static function search_contacts($searchtext, $onlymycourses = false) {
-        global $CFG, $USER;
+        global $CFG, $USER, $PAGE;
         require_once($CFG->dirroot . '/user/lib.php');
 
         // Check if messaging is enabled.
@@ -581,17 +576,11 @@ class core_message_external extends external_api {
             $user->phone1 = null;
             $user->phone2 = null;
 
-            $usercontext = context_user::instance($user->id, IGNORE_MISSING);
-
-            if ($usercontext) {
-                $newuser['profileimageurl'] = moodle_url::make_webservice_pluginfile_url(
-                                                    $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false);
-                $newuser['profileimageurlsmall'] = moodle_url::make_webservice_pluginfile_url(
-                                                        $usercontext->id, 'user', 'icon', null, '/', 'f2')->out(false);
-            } else {
-                $newuser['profileimageurl'] = '';
-                $newuser['profileimageurlsmall'] = '';
-            }
+            $userpicture = new user_picture($user);
+            $userpicture->size = 1; // Size f1.
+            $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
+            $userpicture->size = 0; // Size f2.
+            $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
 
             $user = $newuser;
         }
@@ -863,7 +852,7 @@ class core_message_external extends external_api {
      * @since 2.9
      */
     public static function get_blocked_users($userid) {
-        global $CFG, $USER;
+        global $CFG, $USER, $PAGE;
         require_once($CFG->dirroot . "/message/lib.php");
 
         // Warnings array, it can be empty at the end but is mandatory.
@@ -902,13 +891,9 @@ class core_message_external extends external_api {
                 'fullname' => fullname($user),
             );
 
-            $usercontext = context_user::instance($user->id, IGNORE_MISSING);
-            if ($usercontext) {
-                $newuser['profileimageurl'] = moodle_url::make_webservice_pluginfile_url(
-                                                $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false);
-            } else {
-                $newuser['profileimageurl'] = '';
-            }
+            $userpicture = new user_picture($user);
+            $userpicture->size = 1; // Size f1.
+            $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
 
             $blockedusers[] = $newuser;
         }
diff --git a/mod/chat/classes/external.php b/mod/chat/classes/external.php
index 56d70c69cc4..ba542295996 100644
--- a/mod/chat/classes/external.php
+++ b/mod/chat/classes/external.php
@@ -153,7 +153,7 @@ class mod_chat_external extends external_api {
      * @throws moodle_exception
      */
     public static function get_chat_users($chatsid) {
-        global $DB;
+        global $DB, $PAGE;
 
         $params = self::validate_parameters(self::get_chat_users_parameters(),
                                             array(
@@ -180,13 +180,10 @@ class mod_chat_external extends external_api {
         $returnedusers = array();
 
         foreach ($users as $user) {
-            $usercontext = context_user::instance($user->id, IGNORE_MISSING);
-            $profileimageurl = '';
 
-            if ($usercontext) {
-                $profileimageurl = moodle_url::make_webservice_pluginfile_url(
-                                    $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false);
-            }
+            $userpicture = new user_picture($user);
+            $userpicture->size = 1; // Size f1.
+            $profileimageurl = $userpicture->get_url($PAGE)->out(false);
 
             $returnedusers[] = array(
                 'id' => $user->id,
diff --git a/mod/choice/classes/external.php b/mod/choice/classes/external.php
index 3332e618459..0c8c4261eae 100644
--- a/mod/choice/classes/external.php
+++ b/mod/choice/classes/external.php
@@ -57,7 +57,7 @@ class mod_choice_external extends external_api {
      * @since Moodle 3.0
      */
     public static function get_choice_results($choiceid) {
-        global $USER;
+        global $USER, $PAGE;
 
         $params = self::validate_parameters(self::get_choice_results_parameters(), array('choiceid' => $choiceid));
 
@@ -96,14 +96,11 @@ class mod_choice_external extends external_api {
                         $response = array();
                         $response['userid'] = $userresponse->id;
                         $response['fullname'] = fullname($userresponse, $fullnamecap);
-                        $usercontext = context_user::instance($userresponse->id, IGNORE_MISSING);
-                        if ($usercontext) {
-                            $profileimageurl = moodle_url::make_webservice_pluginfile_url($usercontext->id, 'user', 'icon', null,
-                                                                                         '/', 'f1')->out(false);
-                        } else {
-                            $profileimageurl = '';
-                        }
-                        $response['profileimageurl'] = $profileimageurl;
+
+                        $userpicture = new user_picture($userresponse);
+                        $userpicture->size = 1; // Size f1.
+                        $response['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
+
                         // Add optional properties.
                         foreach (array('answerid', 'timemodified') as $field) {
                             if (property_exists($userresponse, 'answerid')) {
diff --git a/mod/forum/externallib.php b/mod/forum/externallib.php
index 0f9c8263720..d41444d71a6 100644
--- a/mod/forum/externallib.php
+++ b/mod/forum/externallib.php
@@ -384,7 +384,7 @@ class mod_forum_external extends external_api {
      * @since Moodle 2.7
      */
     public static function get_forum_discussion_posts($discussionid, $sortby = "created", $sortdirection = "DESC") {
-        global $CFG, $DB, $USER;
+        global $CFG, $DB, $USER, $PAGE;
 
         $posts = array();
         $warnings = array();
@@ -475,20 +475,15 @@ class mod_forum_external extends external_api {
                 $post->children = array();
             }
 
+            $userpicture = new user_picture($post);
+            $userpicture->size = 1; // Size f1.
+            $post->userpictureurl = $userpicture->get_url($PAGE)->out(false);
+
             $user = new stdclass();
             $user->id = $post->userid;
             $user = username_load_fields_from_object($user, $post);
             $post->userfullname = fullname($user, $canviewfullname);
 
-            // We can have post written by users that are deleted. In this case, those users don't have a valid context.
-            $usercontext = context_user::instance($user->id, IGNORE_MISSING);
-            if ($usercontext) {
-                $post->userpictureurl = moodle_url::make_webservice_pluginfile_url(
-                        $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false);
-            } else {
-                $post->userpictureurl = '';
-            }
-
             // Rewrite embedded images URLs.
             list($post->message, $post->messageformat) =
                 external_format_text($post->message, $post->messageformat, $modcontext->id, 'mod_forum', 'post', $post->id);
@@ -603,7 +598,7 @@ class mod_forum_external extends external_api {
      */
     public static function get_forum_discussions_paginated($forumid, $sortby = 'timemodified', $sortdirection = 'DESC',
                                                     $page = -1, $perpage = 0) {
-        global $CFG, $DB, $USER;
+        global $CFG, $DB, $USER, $PAGE;
 
         require_once($CFG->dirroot . "/mod/forum/lib.php");
 
@@ -696,34 +691,30 @@ class mod_forum_external extends external_api {
                     $discussion->numreplies = (int) $replies[$discussion->discussion]->replies;
                 }
 
+                $picturefields = explode(',', user_picture::fields());
+
                 // Load user objects from the results of the query.
                 $user = new stdclass();
                 $user->id = $discussion->userid;
-                $user = username_load_fields_from_object($user, $discussion);
+                $user = username_load_fields_from_object($user, $discussion, null, $picturefields);
+                // Preserve the id, it can be modified by username_load_fields_from_object.
+                $user->id = $discussion->userid;
                 $discussion->userfullname = fullname($user, $canviewfullname);
 
-                // We can have post written by users that are deleted. In this case, those users don't have a valid context.
-                $usercontext = context_user::instance($user->id, IGNORE_MISSING);
-                if ($usercontext) {
-                    $discussion->userpictureurl = moodle_url::make_webservice_pluginfile_url(
-                        $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false);
-                } else {
-                    $discussion->userpictureurl = '';
-                }
+                $userpicture = new user_picture($user);
+                $userpicture->size = 1; // Size f1.
+                $discussion->userpictureurl = $userpicture->get_url($PAGE)->out(false);
 
                 $usermodified = new stdclass();
                 $usermodified->id = $discussion->usermodified;
-                $usermodified = username_load_fields_from_object($usermodified, $discussion, 'um');
+                $usermodified = username_load_fields_from_object($usermodified, $discussion, 'um', $picturefields);
+                // Preserve the id (it can be overwritten due to the prefixed $picturefields).
+                $usermodified->id = $discussion->usermodified;
                 $discussion->usermodifiedfullname = fullname($usermodified, $canviewfullname);
 
-                // We can have post written by users that are deleted. In this case, those users don't have a valid context.
-                $usercontext = context_user::instance($usermodified->id, IGNORE_MISSING);
-                if ($usercontext) {
-                    $discussion->usermodifiedpictureurl = moodle_url::make_webservice_pluginfile_url(
-                        $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false);
-                } else {
-                    $discussion->usermodifiedpictureurl = '';
-                }
+                $userpicture = new user_picture($usermodified);
+                $userpicture->size = 1; // Size f1.
+                $discussion->usermodifiedpictureurl = $userpicture->get_url($PAGE)->out(false);
 
                 // Rewrite embedded images URLs.
                 list($discussion->message, $discussion->messageformat) =
diff --git a/mod/forum/lib.php b/mod/forum/lib.php
index 42f6db39301..b4a4aaf2309 100644
--- a/mod/forum/lib.php
+++ b/mod/forum/lib.php
@@ -2679,7 +2679,8 @@ function forum_get_discussions($cm, $forumsort="d.timemodified DESC", $fullpost=
         $umfields = "";
         $umtable  = "";
     } else {
-        $umfields = ', ' . get_all_user_name_fields(true, 'um', null, 'um');
+        $umfields = ', ' . get_all_user_name_fields(true, 'um', null, 'um') . ', um.email AS umemail, um.picture AS umpicture,
+                        um.imagealt AS umimagealt';
         $umtable  = " LEFT JOIN {user} um ON (d.usermodified = um.id)";
     }
 
diff --git a/mod/forum/tests/externallib_test.php b/mod/forum/tests/externallib_test.php
index 563429a1a3d..5981e5c0cec 100644
--- a/mod/forum/tests/externallib_test.php
+++ b/mod/forum/tests/externallib_test.php
@@ -383,7 +383,7 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
      * Test get forum posts
      */
     public function test_mod_forum_get_forum_discussion_posts() {
-        global $CFG;
+        global $CFG, $PAGE;
 
         $this->resetAfterTest(true);
 
@@ -451,9 +451,7 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
             'warnings' => array(),
         );
 
-        // Empty picture since it's a user deleted (user3).
-        $userpictureurl = '';
-
+        // User pictures are initially empty, we should get the links once the external function is called.
         $expectedposts['posts'][] = array(
             'id' => $discussion1reply2->id,
             'discussion' => $discussion1reply2->discussion,
@@ -474,12 +472,9 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
             'canreply' => true,
             'postread' => false,
             'userfullname' => fullname($user3),
-            'userpictureurl' => $userpictureurl
+            'userpictureurl' => ''
         );
 
-        $userpictureurl = moodle_url::make_webservice_pluginfile_url(
-            context_user::instance($discussion1reply1->userid)->id, 'user', 'icon', null, '/', 'f1')->out(false);
-
         $expectedposts['posts'][] = array(
             'id' => $discussion1reply1->id,
             'discussion' => $discussion1reply1->discussion,
@@ -500,7 +495,7 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
             'canreply' => true,
             'postread' => false,
             'userfullname' => fullname($user2),
-            'userpictureurl' => $userpictureurl
+            'userpictureurl' => ''
         );
 
         // Test a discussion with two additional posts (total 3 posts).
@@ -508,6 +503,15 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
         $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
         $this->assertEquals(3, count($posts['posts']));
 
+        // Generate here the pictures because we need to wait to the external function to init the theme.
+        $userpicture = new user_picture($user3);
+        $userpicture->size = 1; // Size f1.
+        $expectedposts['posts'][0]['userpictureurl'] = $userpicture->get_url($PAGE)->out(false);
+
+        $userpicture = new user_picture($user2);
+        $userpicture->size = 1; // Size f1.
+        $expectedposts['posts'][1]['userpictureurl'] = $userpicture->get_url($PAGE)->out(false);
+
         // Unset the initial discussion post.
         array_pop($posts['posts']);
         $this->assertEquals($expectedposts, $posts);
@@ -589,7 +593,7 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
      * Test get forum discussions paginated
      */
     public function test_mod_forum_get_forum_discussions_paginated() {
-        global $USER, $CFG, $DB;
+        global $USER, $CFG, $DB, $PAGE;
 
         $this->resetAfterTest(true);
 
@@ -663,12 +667,8 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
         // Create what we expect to be returned when querying the forums.
 
         $post1 = $DB->get_record('forum_posts', array('id' => $discussion1->firstpost), '*', MUST_EXIST);
-        $userpictureurl = moodle_url::make_webservice_pluginfile_url(
-                    context_user::instance($user1->id)->id, 'user', 'icon', null, '/', 'f1');
-
-        // We expect an empty URL since we deleted the user4.
-        $usermodifiedpictureurl = '';
 
+        // User pictures are initially empty, we should get the links once the external function is called.
         $expecteddiscussions = array(
                 'id' => $discussion1->firstpost,
                 'name' => $discussion1->name,
@@ -692,8 +692,8 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
                 'mailnow' => $post1->mailnow,
                 'userfullname' => fullname($user1),
                 'usermodifiedfullname' => fullname($user4),
-                'userpictureurl' => $userpictureurl,
-                'usermodifiedpictureurl' => $usermodifiedpictureurl,
+                'userpictureurl' => '',
+                'usermodifiedpictureurl' => '',
                 'numreplies' => 3,
                 'numunread' => 0
             );
@@ -705,6 +705,16 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
             'discussions' => array($expecteddiscussions),
             'warnings' => array()
         );
+
+        // Wait the theme to be loaded (the external_api call does that) to generate the user profiles.
+        $userpicture = new user_picture($user1);
+        $userpicture->size = 1; // Size f1.
+        $expectedreturn['discussions'][0]['userpictureurl'] = $userpicture->get_url($PAGE)->out(false);
+
+        $userpicture = new user_picture($user4);
+        $userpicture->size = 1; // Size f1.
+        $expectedreturn['discussions'][0]['usermodifiedpictureurl'] = $userpicture->get_url($PAGE)->out(false);
+
         $this->assertEquals($expectedreturn, $discussions);
 
         // Call without required view discussion capability.
diff --git a/rating/classes/external.php b/rating/classes/external.php
index 7570989af73..c877e667c12 100644
--- a/rating/classes/external.php
+++ b/rating/classes/external.php
@@ -75,7 +75,7 @@ class core_rating_external extends external_api {
      * @since Moodle 2.9
      */
     public static function get_item_ratings($contextlevel, $instanceid, $component, $ratingarea, $itemid, $scaleid, $sort) {
-        global $USER;
+        global $USER, $PAGE;
 
         $warnings = array();
 
@@ -146,13 +146,10 @@ class core_rating_external extends external_api {
                     $rating->rating = $maxrating;
                 }
 
-                $profileimageurl = '';
-                // We can have ratings from deleted users. In this case, those users don't have a valid context.
-                $usercontext = context_user::instance($rating->userid, IGNORE_MISSING);
-                if ($usercontext) {
-                    $profileimageurl = moodle_url::make_webservice_pluginfile_url($usercontext->id, 'user', 'icon', null,
-                                                                                    '/', 'f1')->out(false);
-                }
+                // The rating object has all the required fields for generating the picture url.
+                $userpicture = new user_picture($rating);
+                $userpicture->size = 1; // Size f1.
+                $profileimageurl = $userpicture->get_url($PAGE)->out(false);
 
                 $result = array();
                 $result['id'] = $rating->id;
diff --git a/webservice/externallib.php b/webservice/externallib.php
index f26c949e365..ea7d8bcc0b5 100644
--- a/webservice/externallib.php
+++ b/webservice/externallib.php
@@ -71,14 +71,16 @@ class core_webservice_external extends external_api {
      * @since Moodle 2.2
      */
     public static function get_site_info($serviceshortnames = array()) {
-        global $USER, $SITE, $CFG, $DB;
+        global $USER, $SITE, $CFG, $DB, $PAGE;
 
         $params = self::validate_parameters(self::get_site_info_parameters(),
                       array('serviceshortnames'=>$serviceshortnames));
 
         $context = context_user::instance($USER->id);
-        $profileimageurl = moodle_url::make_pluginfile_url(
-                $context->id, 'user', 'icon', null, '/', 'f1');
+
+        $userpicture = new user_picture($USER);
+        $userpicture->size = 1; // Size f1.
+        $profileimageurl = $userpicture->get_url($PAGE);
 
         // Site information.
         $siteinfo =  array(