Sanitizing User Input using Form API - Creating Nodes I'm using D7 Form API to make some custom forms for users that create nodes on submit (using node_submit &amp; node_save functions). This is an example form I'm using:

function create_article_form($form, &amp;$form_state) {

$form['node_title'] = array(
    '#type' =&gt; 'textfield',
    '#title' =&gt; t('Node Title'),
    '#size' =&gt; 20,
    '#required' =&gt; TRUE,
 );

$form['submit_button'] = array(
   '#type' =&gt; 'submit',
   '#value' =&gt; t('Create Node'),
 );

return $form;
}


This works great, but I'm just wondering about sanitization. From my research it seems like the check_plain() function should be used for text fields for security. However, it also causes raw HTML entities to be saved.

For example, I am setting the node title in the submit function like this:

$node-&gt;title = check_plain($form_state['values']['node_title']);


This problem is, if the user enters something like this:

Mike's Tacos


it gets saved in the node title like this:

Mike&amp;#39;s Tacos


So if I output that title anywhere (in a view, in a custom node--XX.tlp.php, etc, it shows in this way.

Can anyone help with how to still use check_plain (or whatever function will provide the best security) but have the value saved with the human-readable format (Mike's Tacos)?
Filters are used for output, not input. It's the Drupal way; save the raw, un-sanitised data in storage, and filter (and cache) when it's being rendered. 

You shouldn't run check_plain() on your node title before saving it, as it will be run through the same function by core/contrib when the node is being rendered, hence the double-encoding you're probably seeing.

If you're responsible for rendering the node title yourself at any point, you should always run it through check_plain() first:

echo check_plain($node-&gt;title);


But always on output, never on input.