What Is Xmlrpc.php in WordPress and Why You Should Disable It

WordPress has always had inbuilt features that let you remotely interact with your site. Face it, sometimes you’ll need to access your website and your computer won’t be anywhere nearby. For a long time, the solution was a file named xmlrpc.php. But in recent years, the file has become more of a pest than a solution.

Below we dive into what xmlrpc.php actually is and why it was created. We also overview the common security issues it causes and how to patch them on your own WordPress site.

What Is Xmlrpc.php?

XML-RPC is a feature of WordPress that enables data to be transmitted, with HTTP acting as the transport mechanism and XML as the encoding mechanism. Since WordPress isn’t a self-enclosed system and occasionally needs to communicate with other systems, this was sought to handle that job.

For example, let’s say you wanted to post to your site from your mobile device since your computer was nowhere nearby. You could use the remote access feature enabled by xmlrpc.php to do just that.

The core features that xmlrpc.php enabled were allowing you to connect to your site via smartphone, implementing trackbacks and pingbacks from other sites, and some functions associated with the Jetpack plugin.

Why Was Xmlrpc.php Created and How Was it Used?

The implementation of XML-RPC goes back to the early days of WordPress before it even became WordPress.

Back in the early days of the internet, when the connections were incredibly slow, the process of writing and publishing to the web was much more difficult and time-consuming. Instead of writing within the browser itself, most people would write offline, then copied and pasted their content onto the web. Still, this process was far from ideal.

The solution (at the time), was to create an offline blogging client, where you could compose your content, then connect to your blog to publish it. This connection was done through XML-RPC. With the basic framework of XML-RPC in place, early apps used this same connection to allow people to log in to their WordPress sites from other devices.

XML-RPC Nowadays

In 2008, with version 2.6 of WordPress, there was an option to enable or disable XML-RPC. However, with the release of the WordPress iPhone app, XML-RPC support was enabled by default, and there was no option to turn off the setting. This has remained true to the present day.

However, the functionality of this file has greatly decreased over time, and the overall size of the file has decreased from 83kb to 3kb, so it doesn’t play as large of a role as it used to.

The Future of XML-RPC

With the new WordPress API, we can expect XML-RPC to be eliminated entirely. Today, this new API is still in the trial phase and can only be enabled through the use of a plugin.

However, you can expect the API to be coded directly into the WordPress core in the future, which will mostly eliminate the need for the xmlrpc.php file altogether.

The new API isn’t perfect, but it provides a more robust and secure solution to the problem that xmlrpc.php addressed.

Why You Should Disable Xmlrpc.php

The biggest issues with XML-RPC are the security concerns that arise. The issues aren’t with XML-RPC directly, but instead how the file can be used to enable a brute force attack on your site.

Sure, you can protect yourself with incredibly strong passwords, and WordPress security plugins. But, the best mode of protection is to simply disable it.

There are two main weaknesses to XML-RPC which have been exploited in the past.

The first is using brute force attacks to gain entry to your site. An attacker will try to access your site using xmlrpc.php by using various username and password combinations. They can effectively use a single command to test hundreds of different passwords. This allows them to bypass security tools that typically detect and block brute force attacks.

The second was taking sites offline through a DDoS attack. Hackers would use the pingback feature in WordPress to send pingbacks to thousands of sites instantaneously. This feature in xmlrpc.php gives hackers a nearly endless supply of IP addresses to distribute a DDoS attack over.

To check if XML-RPC is running on your site, then you can run it through a tool called XML-RPC Validator. Run your site through the tool, and if you get an error message, then it means you don’t have XML-RPC enabled.

If you get a success message, then you can stop xmlrpc.php with one of the two approaches below.

Method 1: Disabling Xmlrpc.php With Plugins

Disabling XML-RPC on your WordPress site couldn’t be easier.

Simply navigate to the Plugins › Add New section from within your WordPress dashboard. Search for Disable XML-RPC and install the plugin that looks like the image below:

install disable xmlrpc plugin

Activate the plugin and you’re all set. This plugin will automatically insert the necessary code to turn off XML-RPC.

However, keep in mind that some existing plugins may utilize parts of XML-RPC, so disabling it completely could cause a plugin conflict or certain elements of your site to no longer function.

If you’d want to only turn certain elements of XML-RPC off, but still allow certain plugins and features to work, then use the following plugins instead:

  • Stop XML-RPC Attack. This plugin will stop all XML-RPC attacks, but it’ll continue to allow plugins like Jetpack, and other automatic tools and plugins to retain access to the xmlrpc.php file.
  • Control XML-RPC Publishing. This allows you to retain control and use over the remote publishing option afforded by xmlrpc.php.

Method 2: Disabling Xmlrpc.php Manually

If you don’t want to utilize a plugin and prefer to do it manually, then follow this approach. It will stop all incoming xmlrpc.php requests before it gets passed onto WordPress.

Open up your .htaccess file. You may have to turn on the ‘show hidden files’ within file manager or your FTP client to locate this file.

Inside your .htaccess file, paste the following code:

  1. # Block WordPress xmlrpc.php requests
  2. <Files xmlrpc.php>
  3. order deny,allow
  4. deny from all
  5. allow from
  6. </Files>

Closing Thoughts

Overall, XML-RPC was a solid solution to some of the problems that occurred due to remote publishing to your WordPress site. However, with this feature came some security holes that ended up being pretty damaging for some WordPress site owners.

To ensure your site remains secure it’s a good idea to disable xmlrpc.php entirely. Unless you require some of the functions needed for remote publishing and the Jetpack plugin. Then, you should use the workaround plugins that allow for these features, while still patching the security holes.

In time, we can expect the features of XML-RPC to become integrated into the new WordPress API, which will keep remote access and the like, without sacrificing security. But, in the meantime, it’s a good idea to protect yourself from the potential XML-RPC security holes.

Have you blocked XML-RPC access via a plugin or manually? Or experienced any security issues from having it active in the first place? Please share your experience in the comments below.

How to Install Free SSL From Let’s Encrypt on Shared Hosting


Let’s Encrypt introduced free SSL certificates quite some time ago. It made possible for website owners to offer encrypted HTTPS connection for their visitors totally free of charge. Before Let’s Encrypt, the only way to get a valid SSL certificate was to purchase it from a seller.

Let’s Encrypt SSL certificate can be installed with just a few lines of code on a VPS or dedicated server, however, installation on shared hosting accounts is still a bit complicated (unless it uses cPanel).

Hostinger doesn’t yet have an auto-installer for Let’s Encrypt SSL certificates (we are working on this), but there is a workaround – it can be installed manually using ACME client written in PHP and composer.

This tutorial shows how to install free SSL from Let’s Encrypt on Hostinger shared hosting.

What you’ll need

Before you begin this guide you’ll need the following:

  • Hostinger Premium or Business account.
  • SSH client.

Step 1 – Enabling SSH Access

SSH access is required in order to install SSL on shared Hostinger account. By default it’s disabled, but you can easily enable it by following these steps:

  1. Access Hostinger control panel and navigate to SSH section.
    Hostinger SSH Section
  2. Click on Disabled to change status to Enabled. Hit Update button.
    Hostinger Enable SSH
  3. The page will refresh and you should see information required to connect via SSH. Write it down as you will need it in the next step.
    Hostinger SSH Information

Step 2 – Installing ACME client and Composer

We will use ACME client written in PHP and composer to generate Let’s Encrypt SSL certificate.

First of all, you will have to connect to your hosting account via SSH and download all required components. If you are running macOS or Linux, you can use terminal to connect via SSH, Windows users can take advantage of Putty SSH client.

  1. Connect to your hosting account using SSH information from Step 1.3. In our example, it would be:
    ssh x123011738@ -p 65002
  2. Clone acme client from github repository. Cloning can be done by executing the following command:
    git clone https://github.com/kelunik/acme-client
  3. Access ACME client directory:
    cd acme-client
  4. Download and install the composer:
    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"; 
    php composer-setup.php;
    php -r "unlink('composer-setup.php');";
    php composer.phar install --no-dev

Step 3 – Generating SSL Certificate

Once you have downloaded and installed ACME client and composer, you can proceed and generate free SSL from Lets Encrypt. Firstly, register an account by running this command:

php bin/acme setup --server letsencrypt --email your@email.com

Note that you need to change your@email.com to your actual email.

The process of generating SSL certificate is pretty straightforward. Execute the following command:

php bin/acme issue --domains yourdomain.com:www.youdomain.com --path /home/x123011738/public_html:/home/x123011738/public_html --server letsencrypt

Change yourdomain.com to your real domain name and x123011738 to your actual username (you can check it on Step 1.3).

If certificate was issued successfully, you will see the following message:

Requesting certificate ...
Successfully issued certificate.
See /home/x123011738/acme-client/data/certs/acme-v01.api.letsencrypt.org.directory/yourdomain.com

ACME client generated certificate and private key files. Unfortunately, installation cannot be done via SSH due to security restrictions. Therefore, you first need to manually copy certificate and private key files to your computer. It can be done using simple copy / paste method. Firstly navigate to the directory where private key and certificate files are stored:

cd /home/x123011738/acme-client/data/certs/acme-v01.api.letsencrypt.org.directory/yourdomain.com

Use cat command to see contents of fullchain.pem file:

cat fullchain.pem

Copy the part marked in red and save it in a text file on your computer. Name the text file certificate.txt.

Let's Encrypt Certificate Copy

Now do the same with private key:

cat key.pem

Copy the private key (as shown in the screenshot) and save it in a text file as well. Name it privatekey.txt.

Let's Encrypt Key Copy

The hardest part is over. You can now proceed with the installation of SSL certificate.

Step 3 – Installing Certificate via Hostinger members area

At this step you should already have certificate and private key saved in txt files on your computer. The final step is to install SSL certificate on your hosting account. It can be done via SSL section:

  1. Access Hostinger members area and navigate to SSL section.
    Hostinger SSL Section
  2. Select the domain from the drop down menu for which you want to install SSL certificate.
  3. Paste contents from certificate.txt to Certificate:(CRT) and contents from privatekey.txt to Private Key:(KEY) fields. Press Install button once you are done.
    Installing SSL via SSL Section
  4. Once the installation is complete, you will see a success message.
    SSL Install Success

That’s it, you have successfully installed free SSL from Let’s Encrypt on shared hosting account. Your domain name will now work via HTTPS protocol.

Step 4 – Checking expiration date and renewing SSL certificate

Let’s Encrypt SSL certificates are set to expire every 90 days. You can check its expiration date via SSH using the following command:

php acme-client/bin/acme check --name yourdomain.com --server letsencrypt

You can also try to automatically renew Let’s Encrypt SSL certificate with a cron job. For example, in order to automatically renew SSL certificate, you can set cron job to run the following command every other month:

php acme-client/bin/acme issue --domains yourdomain.com:www.yourdomain.com --path /home/x123011738/public_html:/home/x123011738/public_html --server letsencrypt

On Hostinger, cron jobs can be created on Advanced Cron Jobs section. You can use the following settings:Cron Job to Renew Let's Encrypt on Shared Hosting


  • Common Option(s) – Once a month (0 0 1 * *)
  • Minute(s) – :00 top of the hour (0)
  • Hour(s) – 12 a.m. Midnight (0)
  • Day(s) – 1st (1)
  • Month(s) – Every other month (*/2)
  • Weekday(s) – Every weekday (*)


Let’s Encrypt SSL certificates are great if you want to run your websites on HTTPS but don’t want to invest any money. This tutorial intended to show you a workaround you can use to install free SSL from Let’s Encrypt on shared hosting account.

How to Hide Specific Pages in the WordPress Admin

If you’ve built a custom website using WordPress, perhaps you’ve created some pages like “Login,” “Register,” “Modify Profile” and so on. While this gives you the power to use WordPress template files, it also makes your system somewhat user-prone.

What if a user changes a permalink or deletes the page altogether?

In this Weekend WordPress Project I’ll explore a way of preventing this, while also providing a better user experience.

The Plan

The plan is that there will be a set of a pages not visible to anyone, including admins. How we put this in place can differ greatly:

  1. You could create these pages programmatically using the wp_insert_post() function
  2. You could create the pages and then put the hiding in place
  3. You could create a new user role who does see all pages but any other role – including admins – don’t see the special ones
  4. You could check when a post is deleted using the delete_post hook and simply re-create it or prevent deletion if it is a special page

I will choose to show number three here because I believe it provides the best user experience for the developer and the end user.

The other aspect of this we need to think about is how we determine what a special page is. We have a couple of options:

  1. Define a list of IDs
  2. Define a list of post names
  3. Use a category or taxonomy to indicate special pages

I chose option 3 here also because it gives me the most flexibility. Maintaining a set of IDs or post names is not something I want to do – the less error-prone the better. Taxonomy terms can be assigned from the WordPress backend so I can do all the management there.

Step 0 – Create a Plugin

All the code required for this example to work can be added to your theme’s functions.php file. While this is fine for testing or for custom built projects, it is perhaps best to add the code to a plugin.

If you don’t know how to create a plugin take a look at out getting started with plugin development article, it has all the info you need to get started.

Step 1 – Create a New Role

We should only try and create a new role once, when our plugin is activated. This can be done by using the register_activation_hook() function. Here’s how:

register_activation_hook( __FILE__, ‘my_initial_setup’ );
function my_initial_setup() {
$admin = get_role( ‘administrator’ );
$overlord_caps = $admin->capabilities;
$overlord_caps[] = ‘be_overlord’;
$role = add_role( ‘overlord’, ‘Overlord’, $overlord_caps );
view raw new-role.php hosted with ❤ by GitHub

We copy all the capabilities of the admin role and add them to our new custom role. I’ve also added a custom capability – be_overlord – to make sure we have a custom capability when using the current_user_can() function.

Note that if you’ve already activated your plugin you can remove the hook and just run the function by itself to create the role.

Step 2 – Create a Custom Taxonomy

To create a custom taxonomy we’ll use the register_taxonomy() function. You can read all about it in the WordPress Codex, but the example below should be easy to understand.

add_action( ‘init’, ‘ny_page_category’ );
function ny_page_category() {
$show_ui = ( current_user_can( ‘be_overlord’ ) ) ? true : false;
$labels = array(
‘name’ => ‘Page Categories’,
‘singular_name’ => ‘Page Category’,
‘search_items’ => ‘Search Page Categories’,
‘all_items’ => ‘All Page Categories’,
‘parent_item’ => ‘Parent Page Category’,
‘parent_item_colon’ => ‘Parent Page Category:’,
‘edit_item’ => ‘Edit Page Category’,
‘update_item’ => ‘Update Page Category’,
‘add_new_item’ => ‘Add New Page Category’,
‘new_item_name’ => ‘New Page Category Name’,
‘menu_name’ => ‘Page Categories’,
$args = array(
‘hierarchical’ => true,
‘labels’ => $labels,
‘show_ui’ => $show_ui,
‘query_var’ => true,
‘rewrite’ => array( ‘slug’ => ‘page_category’ ),
register_taxonomy( ‘page_category’, array( ‘page’ ), $args );
view raw page-category.php hosted with ❤ by GitHub

The only unusual feature in the code above is the definition of the $show_ui variable. We want the taxonomy to always be available but we don’t want regular users to be able to assign them. Therefore if someone is logged in as an overlord we’ll show the user interface, otherwise we’ll hide it.

Finally, let’s create a term, which we’ll assign to our special pages. I chose to call this “System Page.” Create it and assign it to all pages you would like to hide in the admin.

System Page Term

Step 3 – Modify the Admin Post List

The final step is to make sure WordPress excludes our system pages from the admin. This can be done with the pre_get_posts hook. Beware, this hook can potentially affect all queries on your site, from your homepage to your admin. Use the proper conditional tags as I have done in the example below:

add_action( ‘pre_get_posts’, ‘my_hide_system_pages’ );
function my_hide_system_pages( $query ) {
if( is_admin() && !empty( $_GET[‘post_type’] ) && $_GET[‘post_type’] == ‘page’ && $query->query[‘post_type’] == ‘page’ && !current_user_can( ‘be_overlord’ ) ) {
$query->set( ‘tax_query’, array(array(
‘taxonomy’ => ‘page_category’,
‘field’ => ‘slug’,
‘terms’ => array( ‘system-page’ ),
‘operator’ => ‘NOT IN’
view raw pre-get-posts.php hosted with ❤ by GitHub

The idea here is that pre_get_posts allows us to modify queries before they are run. We hook into the query, making sure to modify only the one we want by using conditional tags. In our case we check to make sure we are in the admin, the post type is “page” and the current user is not the overlord.

We then set a taxonomy query using the set() method available in the WP_Query class. If you’d like a more detailed look at WordPress queries take a look at our article titled An in-depth guide to conquering WP_Query.


All done! We now have a user-friendly way of specifying pages that no one – not even admins – can touch. As overlords we can log in and manage these pages as needed of course.

The benefit of this method is that it gets out of the way for regular users but retains the flexibility to let overlords manage things from the backend.

Password Protect WordPress Admin (wp-admin) Directory

Login to your cPanel. Scroll down till you see the Security Tab. Click on the “Password Protect Directories” icon.

Password Protect Directories

When you click on that, a lightbox popup will show up asking for directory location. Just click on web root. Once you are there, navigate to the folder where your WordPress is hosted. Then click on the /wp-admin/ folder. You will see a screen like this:

Security Settings for a Folder

Simply check the box to password protect the directory. Then create a user for the directory. That is it. Now when you try to access your wp-admin directory, you should see an authentication required box like this:

Authentication Required

Manual Method

First create a .htpasswds file. You can do so easily by using this generator. Upload this file outside your /public_html/ directory. A good path would be:


Then, create a .htaccess file and upload it in /wp-admin/ directory. Then add the following codes in there:

AuthName "Admins Only"
AuthUserFile /home/yourdirectory/.htpasswds/public_html/wp-admin/passwd
AuthGroupFile /dev/null
AuthType basic
require user putyourusernamehere

You must update your username in there. Also don’t forget to update the AuthUserFile location path.

I have a 404 Error or a Too many redirects error

Well this can happen depending on how your server is configured. To fix this issue, open your main WordPress .htaccess file and add the following code there before the WordPress rules start.

ErrorDocument 401 default

Well there you have it. Now you have double authentication for your WordPress admin area. This is a good alternative to limiting wp-admin access by IP address.

Update: Here is how to fix the Admin Ajax Issue

If you password protect your WordPress Admin directory, then it will break the Ajax functionality in the front-end (if it is being used). In our case, we don’t have any plugins that is using ajax in the front-end. But if you do, then here is how you fix that issue.

Open the .htaccess file located in your /wp-admin/ folder (This is NOT the main .htaccess file that we edited above).

In the wp-admin .htaccess file, paste the following code:

<Files admin-ajax.php>
    Order allow,deny
    Allow from all
    Satisfy any

Leverage browser caching

What is browser caching?

  • Browser caching stores webpage resource files on a local computer when a user visits a webpage.
  • “Leveraging” browser caching is when a webmaster has instructed browsers how their resources should be dealt with.

When a web browser displays your webpage it has to load several things like your logo, your CSS file, and other resources.

What browser caching does is “remember” the resources that the browser has already loaded. When a visitor goes to another page on your website your logo, CSS files, etc. do not need to be loaded again, because the browser has them “remembered” (saved). This is the reason that the first view of a web page takes longer than repeat visits.

When you leverage browser caching, your webpage files will get stored in the browser cache. Your pages will load much faster for repeat visitors and so will other pages that share those same resources.

If you have tested your webpage for speed and found out that you need to leverage browser caching, here is how you do it.

How to leverage browser caching

  1. Change the request headers of your resources to use caching.
  2. Optimize your caching strategy.

Change the request headers of your resources to use caching

For most people, the way to enable caching is to add some code to a file called .htaccess on your web host/server.

This means going to the file manager (or wherever you go to add or upload files) on your webhost.

The .htaccess file controls many important things for your site. If you are not familiar with the .htaccess file, please read my working with .htaccess article to get some know how before changing it.

Browser caching for .htaccess

The code below tells browsers what to cache and how long to “remember” it. It should be added to the top of your .htaccess file.

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg “access 1 year”
ExpiresByType image/jpeg “access 1 year”
ExpiresByType image/gif “access 1 year”
ExpiresByType image/png “access 1 year”
ExpiresByType text/css “access 1 month”
ExpiresByType text/html “access 1 month”
ExpiresByType application/pdf “access 1 month”
ExpiresByType text/x-javascript “access 1 month”
ExpiresByType application/x-shockwave-flash “access 1 month”
ExpiresByType image/x-icon “access 1 year”
ExpiresDefault “access 1 month”

Save the .htaccess file and then refresh your webpage.

How to set different caching times for different file types

You can see in the above code that there are time periods like “1 year” or “1 month”. These are associated with file types, as an example the above code states that a .jpg file (image) should be cached for a year.

If you want to change that and say you want your jpg images cached for a month you would simply replace “1 year” with “1 month”. The values above are pretty optimized for most webpages and blogs.

Alternate caching method for .htaccess

The above method is called “Expires” and it works for most people using .htaccess so it takes care of caching for most people who are just getting started.

After you are more comfortable with caching, you may want to try Cache-Control, another method of caching which gives us more options.

It is also possible the expires method did not work for your server, in that case you may want to try to use Cache-Control.


Note: I have made a more complete guide to Cache-Control here.

Cache-Control allows us to have a bit more control of our browser caching and many people find it easier to use once setup.

Example use in .htaccess file:

# 1 Month for most static assets
<filesMatch “.(css|jpg|jpeg|png|gif|js|ico)$”>
Header set Cache-Control “max-age=2592000, public”

The above code is setting a cache control header depending on file type.

How cache-control works

Let’s take the above code line by line.

# 1 Month for most static assets

The above line is just a note. It does not do anything except notate what we are doing. The .htaccess file ignores lines that start with the character #. This note is recommended as you may have several different sets of these as your caching solution grows.

<filesMatch “.(css|jpg|jpeg|png|gif|js|ico)$”>

The above line is saying that “if the file is one of these types, then we will do something to it…

The important part of this line is to notice that there are different types of files listed (css, js, jpeg, png, etc.) and that the caching instructions that follow will apply to those file types. As an example, if you did not want your jpg files to be cached for this amount of time you could delete “jpg” from this line or if you wanted to add html to this you could just add “html” to this line.

Header set Cache-Control “max-age=2592000, public”

The above line is where the actual headers are inserted and the values given.

  • The “Header set Cache-Control” part is setting a header.
  • The “max-age=2592000” part is stating how long it should be cached (using seconds). In this case we are caching for one month which is “2592000” seconds.
  • The “public” part is stating that this is public (which is good if you want it to be cached).


The above line is closing the statement and ends the block of code.

Common caching issue

If you list your html and images to be cached for one year or some other long time period, remember that this can mean if you make a change to your pages they may not be seen by all users. This is because the users will look to cached files rather than the live ones. If you have file that you tweak occasionally (example – a CSS file) you can overcome the cache issue by using URL fingerprinting.

URL fingerprinting

Getting a fresh (not cached) file resource is possible by having a unique name. An example would be if our css file was named “main.css” we could name it “main_1.css” instead. The next time we change it we can call it “main_2.css”. This is useful for files that change occasionally.

Caching methods

It is important to specify one of Expires or Cache-Control max-age, and one of Last-Modified or ETag, for all cacheable resources. It is redundant to specify both Expires and Cache-Control: max-age, or to specify both Last-Modified and ETag.

Enable/Disable Directory File Listing (Linux)

Follow the steps below to enable file listing in your Linux package, making the files stored in your subfolders visible:

On Linux hosting packages, Directory Listing (file listing, file browsing, etc) is disabled by default. Because of this, if you would try to access a subfolder of your webspace filled with only pictures (such as http://domain.com/images/), you would likely receive a 404 Error. The 404 error generates because the web server was looking for a default or index page in the images/ subfolder. Since only pictures are saved in this subfolder, the server does not display the list of files but produces an error that no page was found. This is the default action so that no one is able to view a listing of your potentially sensitive web site files should they stumble upon this subfolder.

Sometimes it will be necessary to display the files contained in a folder for easy access (with no login). To enable this, you have to create (or edit an existing) .htaccess file.

The .htaccess file is a file where you can add some configuration for the web server. The .htaccess file is recursive meaning the configuration within the file will apply to the folder where it is saved as well as subfolders.

Enable Directory Listing
To enable Directory Listing, create a .htaccess (or edit an existing one) and add the following text below on a new line.

Options +Indexes

Disable Directory Listing
To disable Directory Listing, remove the above line from the relevant .htaccess file. To force disable the Directory Listing (such as in a subfolder where the parent folder already has Directory Listing enabled), add the line below to your .htaccess file.

Options -Indexes

Save the .htaccess file in the folder where you want the files publicly listed. If you are creating/editing the file on a Windows machine, use a basic text editor like Wordpad or Notepad. Save the file as htaccess.txt first and then upload the file to the correct folder. Once uploaded, you can then rename the file to .htaccess.

Change default “Select Category” text in categories dropdown widget in WordPress

Add a function like this one in your functions.php in the stylesheet directory:

function ChangeSelectTitle($cat_args){
    $cat_args['show_option_none'] = __('My Category');
    return $cat_args;
add_filter('widget_categories_dropdown_args', 'ChangeSelectTitle');

Where My Category is the new title you want instead of Select Category