diff --git a/ChangeLog b/ChangeLog
index 8091fa647104b29f48f70be5190927cb3f50d8ce..52fb24e0a0be91be0344dd0ab5bfd7f149ce2d40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,5 @@
 train-2012.06.08 (in progress):
-  *
+  * Support non-english passwords: issue #1631
 
 train-2012.05.25:
   * many KPI improvements: #1597, #1613
diff --git a/lib/http_forward.js b/lib/http_forward.js
index d88cbd85de18c4f97f85fbb563fc0929dc05c30d..819142ee8332f24a0ef41fe0cce6e9a1cb93d034 100644
--- a/lib/http_forward.js
+++ b/lib/http_forward.js
@@ -93,7 +93,7 @@ exports.forward = function(dest, req, res, cb) {
     var data;
     if (req.headers['content-type'].indexOf('application/json') === 0) data = JSON.stringify(req.body);
     else data = querystring.stringify(req.body);
-    preq.setHeader('content-length', data.length);
+    preq.setHeader('content-length', Buffer.byteLength(data));
     preq.write(data);
     preq.end();
   } else {
diff --git a/lib/wsapi_client.js b/lib/wsapi_client.js
index 256fcf71c6e395fad3a18dae23fadbb5cef2c0fc..c6ae5bd4208c15fb8a2f94fa219e7c6cb3bd626f 100644
--- a/lib/wsapi_client.js
+++ b/lib/wsapi_client.js
@@ -129,7 +129,7 @@ exports.post = function(cfg, path, context, postArgs, cb) {
     if (typeof postArgs === 'object') {
       postArgs['csrf'] = csrf;
       body = JSON.stringify(postArgs);
-      headers['Content-Length'] = body.length;
+      headers['Content-Length'] = Buffer.byteLength(body);
     }
 
     var req = meth.request({
diff --git a/tests/simple-stage-user-utf8-password.js b/tests/simple-stage-user-utf8-password.js
new file mode 100644
index 0000000000000000000000000000000000000000..cdd07a8dafbd20b7d17f081a8ecd3211c645892d
--- /dev/null
+++ b/tests/simple-stage-user-utf8-password.js
@@ -0,0 +1,82 @@
+#!/usr/bin/env node
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+require('./lib/test_env.js');
+
+const
+assert = require('assert'),
+vows = require('vows'),
+start_stop = require('./lib/start-stop.js'),
+wsapi = require('./lib/wsapi.js');
+
+var suite = vows.describe('simple-stage-user-utf8-password');
+
+// disable vows (often flakey?) async error behavior
+suite.options.error = false;
+
+start_stop.addStartupBatches(suite);
+
+const
+TEST_DOMAIN = 'example.domain',
+TEST_ORIGIN = 'http://127.0.0.1:10002',
+TEST_SITE = 'http://example.com:652';
+
+// This test simply stages a secondary user. It does so for two users,
+// one with a password that is only ascii, and the other with non-ascii
+// characters in the password (GH-1631).
+
+const test_users =
+  [{
+    email: 'testuser1@' + TEST_DOMAIN,
+    password: 'fakepass',
+  },
+  {
+    email: 'testuser2@' + TEST_DOMAIN,
+    password: 'поддельный пароль', // Russian 'fake password' (34 bytes UTF-8)
+  }];
+
+function makeBatch(site, user) {
+  var batch = {
+    "staging an account": {
+      topic: wsapi.post('/wsapi/stage_user', {
+        site: site,
+        email: user.email,
+        pass: user.password,
+      }),
+      "is 200 OK": function(err, r) {
+        assert.strictEqual(r.code, 200);
+      },
+      "and a token": {
+        topic: function() {
+          start_stop.waitForToken(this.callback);
+        },
+        "is obtained": function (t) {
+          assert.strictEqual(typeof t, 'string');
+        },
+        "and the token can be used": {
+          topic: function(token) {
+            wsapi.post('/wsapi/complete_user_creation', { token: token }).call(this);
+          },
+          "to verify email ownership": function(err, r) {
+            assert.equal(r.code, 200);
+            assert.strictEqual(JSON.parse(r.body).success, true);
+            token = undefined;
+          }
+        }
+      }
+    }
+  };
+  return batch;
+}
+
+suite.addBatch(makeBatch(TEST_SITE, test_users[0]));
+suite.addBatch(makeBatch(TEST_SITE, test_users[1]));
+
+start_stop.addShutdownBatches(suite);
+
+// run or export the suite.
+if (process.argv[1] === __filename) suite.run();
+else suite.export(module);